Go 1.13 was released on September 3 2019.
This document summarizes changes since 1.12.
go mod
Improved go mod
:
go build
Build multiple binaries with single go build
Provide a directory as -o
argument to go build
to build multiple binaries at once: go build -o dir path/to/main/packages/...
$ mkdir apps
$ go build -o apps/ ./app/...
$ ls -l apps/
total 38532
-rwxr-xr-x 1 valyala valyala 12403288 Aug 25 17:03 vminsert
-rwxr-xr-x 1 valyala valyala 13366272 Aug 25 17:03 vmselect
-rwxr-xr-x 1 valyala valyala 13652144 Aug 25 17:03 vmstorage
Trim file paths recorded in the binary
As part of debugging information recorded in the binary, go build
includes file paths of source files.
By default they are full paths, which depend on the machine used to compile the code.
Option -trimpath
to go build
makes them system independent.
This helps to make reproducible builds.
$ go build ./cmd/printast
$ strings printast | grep main.go
/Users/kjk/src/markdown/cmd/printast/main.go
$ go build -trimpath ./cmd/printast
$ strings printast | grep main.go
github.com/gomarkdown/markdown@/cmd/printast/main.go
/Users/kjk/src/markdown/cmd/printast/main.go
: default path for main.go
github.com/gomarkdown/markdown@/cmd/printast/main.go
: system-independent path with -trimpath
Language and standard library
Error wrapping
There’s a standard way of wrapping errors.
To create an error that wraps another error, implement Unwrap() error
interface which returns wrapped error (or nil
if nothing is wrapped).
To easily wrap an error and add additional information, use %w
argument to fmt.Errorf()
. It creates a new error that wraps error provided as %w
argument.
To check if error of type *myError
is wrapped by error err
, do errors.Is(err, &myError{})
.
To extract wrapped error of specific type from error err
, use errors.As(err, unwrapped)
err1 := &myError{}
err2 := fmt.Errorf(“%w”, err1)
errors.Unwrap(err2) == err1
errors.Is(err2, err1) == true
var me myError
errors.As(err2, &me) == true
Number literals
- Digit separators:
1_000_000
== 1000000
- Binary literals:
0b11100100
- Esoteric floating point literals:
0x1.0p-1021
Better out of range panic message
Out of range panic messages now include the index that was out of bounds and the length (or capacity) of the slice.
runtime error: index out of range [3] with length 1
TLS 1.3 enabled by default
New escape analysis
It more aggressively optimizes ~188 instances, but more pessimistically optimizes 11.
Method inlining (mid-stack inlining)
The major part of it has been enabled in 1.12. sync.Mutex
fast paths are inlined in 1.13
// F is inlined if fast path is small
func F(x int) {
if x > 0 {
slowPath() // manually outlined
}
// fast path
}
sync.Pool and GC
Objects in sync.Pool
survive GC now.
var p sync.Pool
var obj object
p.Put(&obj)
runtime.GC()
p.Get().(*object) == obj
Faster defer
A single defer per func is allocated on stack instead of heap in 1.13, so it performs faster by up to 30%
type Counter struct {
mu sync.Mutex
n int
}
func (c *Counter) Inc() {
c.mu.Lock()
defer c.mu.Unlock() // <- this defer is faster now
c.n++
}
Other
Divisibility check optimizations
n % C == 0
is now 2x faster for constant C
.
Faster encoding/json
- multiple encoding/json optimizations by Daniel Martí
- up to 30% better parsing performance
Faster strings
and bytes
packages
- optimized
ToLower
and ToUpper
for ASCII (up to 3.5x faster)
- speed up
TrimSpace
for common ASCII cases (up to 5x faster)
- use Rabin-Karp algorithm for
LastIndex
(up to 2x faster)
Faster math/big
Optimizations in math/big
usually improve performance for cryptography:
- remove bounds checks in pure Go implementations (up to 15% faster)
- add fast path for
addVW
for large z (up to 10x faster)
- rewrite pure Go implementations to use math/bits (up to 3x faster)
Faster **sync**
These optimizations were possible thanks to mid-stack inlining:
Once.Do
2x faster with inlined fast path
- better fast path performance for
Mutex.Lock
/ Unlock
by up to 30%
Faster startup time
- Go programs already were starting faster than Java programs
- 1.13 reduces startup times further by removing unneeded initializations
go env
execution times are reduced to less than 150ms
Faster on ARM / ARM64
ARM optimizations should improve performance on mobile phones, raspberry pi and arm servers:
- optimize
mulAddVWW
on arm64 (up to 30% faster)
- intrinsify
math/bits.Sub64
for arm64 (up to 3.5x faster)
- intrinsify
math/bits.Add64
for arm64 (up to 3x faster)
- add assembly implementation of
Count
/CountString
on arm (up to 50% faster)
- use word-wise comparison for
Equal
on arm (up to 3x faster)
- eliminate unnecessary type conversions in
TrailingZeros16
/ TrailingZeros8
for arm
- use word-wise comparison for
Compare
on arm (up to 3.5x faster)
- optimize
math/bits.Div32
for arm64