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 ToLowerandToUpperfor ASCII (up to 3.5x faster)
- speed up TrimSpacefor 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 addVWfor 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.Do2x faster with inlined fast path
- better fast path performance for Mutex.Lock/Unlockby 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 envexecution 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 mulAddVWWon arm64 (up to 30% faster)
- intrinsify math/bits.Sub64for arm64 (up to 3.5x faster)
- intrinsify math/bits.Add64for arm64 (up to 3x faster)
- add assembly implementation of Count/CountStringon arm (up to 50% faster)
- use word-wise comparison for Equalon arm (up to 3x faster)
- eliminate unnecessary type conversions in TrailingZeros16/TrailingZeros8for arm
- use word-wise comparison for Compareon arm (up to 3.5x faster)
- optimize math/bits.Div32for arm64