What's new in Go 1.13

Krzysztof Kowalczyk
Sep 1 · 4 min read · 311 views
Go 1.13 was released on September 3 2019.
This document summarizes changes since 1.12.
Full release notes: https://golang.org/doc/go1.13

Toolchain

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

Performance optimizations

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

More Go resources

  • Essential Go is a free, comprehensive book about Go that I maintain

Go programmer for hire

If you're looking for a Go programmer for contract work, let's talk.
Updating...

Share on