Vincent Blanchon
Sep 4 · 7 min read
Illustration created for “A Journey With Go”, made from the original Go Gopher, created by Renee French.

The history of Go is must-have knowledge for every developer. Knowing the major changes released across the years helps you to understand the mindset of Go and the strengths/weaknesses of the language for each version. For more details about a specific version, the changelogs are linked to each version number.

Go 1.0 — March 2012:

The first version of Go shipped a compatibility document that guarantees compatibility with the future releases in order to not break existing programs.

This first version already has the go tool pprof command that is a slight variant of Google’s pprof C++ profiler and go vet (previously go tool vet) command that reports likely mistakes in packages.

Go 1.1 — May 2013:

This version of Go was dedicated to improving the language (compiler, garbage collector, map, go scheduler) and its performances. Here is an example of the improvements:

This version also embeds the race detector, an essential tool in the language.

You can find more information about race detector in my article “Race Detector with ThreadSanitizer”.

The Go scheduler has been re-written to significantly increase the performance. The Go scheduler is now designed like this:

M is an OS thread and P represents a processor (number of P cannot exceed GOMAXPROCS) where each P as a local goroutine queue. Prior to 1.1, P not exist and the goroutines were managed at a global level with a single global mutex. Along with this improvement, work-stealing has been implemented and allows one P to steal goroutines from another P:

For more information about the Go scheduler and the work-stealing, check out “Go’s work-stealing scheduler” By Jaana B. Dogan.

Go 1.2 — December 2013:

The command test now supports code coverage and provides a new command, go tool cover, that provides coverage statistics:

It can also provide coverage information:

Go 1.3 — June 2014:

An important improvement in the stack management was done in this version. The stack now allocates contiguous segments of memory and will improve the efficiency of the allocation, allowing the language to decrease the stack size to 2KB in the next release.

It also improved some components that were slow due to some bad split, where the stack intensively allocate/free stack segment. Here is an example of the json package that shows how it is sensitive to the stack size:

contiguous stack

Using a contiguous stack has fixed the slowness of this component. Here is another example of the html/template package where the performance was also sensitive to the stack size:

More information about it in my article “How Does the Goroutine Stack Size Evolve?

This version also released the Pool from the sync package. This component allows us to re-use structure later and reduce the number of allocations, and will be source of many improvements in the Go ecosystem, like encoding/json or net/http in the standard library or packages like zap in the Go community.

There is more information about this in my article “Understand the Design of Sync.Pool”.

Go team also worked on some channel improvements in order to get them faster. Here are the benchmarks on Go 1.2 and Go 1.3:

Go 1.2 vs Go 1.3 for the channels

Go 1.4 — December 2014:

With this version is shipped an official support for Android that allows to write simple Android apps using only Go code.

Also, most of the runtime that was previously written in C and assembler has been translated to Go, allowing the heap size to be reduced by 10/30% thanks to a more accurate garbage collector.

While not related to the release itself, this coincides with the project’s move from Mercurial to Git and Google Code to Github.

Go also released the go generate command that simplifies the code generation by scanning the code for the directive //go:generate that provides the command to generate a piece of code.

More information about this is available in the Go blog and the post “Generating code”.

Go 1.5 — August 2015:

For this new version, the released was shifted by two months in order to have the releases in August and February of each year:

The garbage collector has been totally re-engineered for this version. Thanks to a concurrent collector, the latencies during the collection have been reduced a lot. Here is an example of a production server for Twitter where latencies go from 300ms to 30ms:

This version also released the execution trace, available via the command go tool trace. The traces generated during the tests, or during the runtime, can be displayed in a browser window:

Original Go Execution Tracer Document

Go 1.6 — February 2016:

The support for HTTP/2 by default when using HTTPS is the most significant change from this new version.

The garbage collector latency was also reduced in this version:

Go 1.7 — August 2016:

This version released the context package that gives users a way to deal with timeout and task cancellation.

To learn more about context, check out my article “Context and Cancellation by Propagation.”

The compiler toolchain has been optimized to offer faster compilation and binaries smaller, sometimes by as much as 20–30%.

Go 1.8 — February 2017:

The improvement on the garbage collector drops pause under the milliseconds:

The remaining pauses are identified and will be fixed in the next releases to reach pauses usually around 100 microseconds.

This version also improved the defer functions:

There is more information about it in my article “How Does defer Statement Work?”.

Go 1.9 — August 2017:

The aliases are now available in this version:

type byte = uint8

Here byte is an alias of uint8.

The sync package added a new Map type, safe for concurrent access.

More information about it is in my article “Concurrency Access with Maps.”

Go 1.10 — February 2018:

A new smart cache was introduced in the test package and now caches test results when they passed. It allows the developer to not run the tests again if no changes have been done on it and save time when running the test suite:

first run:
ok /go/src/retro 0.027s
second run:
ok /go/src/retro (cached)

The go build command now maintains a cache of recently built packages in order to speed up builds.

This release has no substantial change in the garbage collector but a new SLO (Service-Level Objective) has been defined for the garbage collector:

Go 1.11 — August 2018:

Go 1.11 brought one new important feature with Go modules. Go modules comes in response to the major challenge the Go community is facing to according to the surveys done the past years:

Go Survey 2018

The second feature is an experimental one with the port to WebAssembly with the ability for the developers to compile Go programs to a binary format compatible with four major web browsers.

Go 1.12 — February 2019:

go vet command was rewritten based on the analysis package that gives more flexibility and allows developers to write their own checker.

More information about it in my article “How to Build Your Own Analyzer”.

Go 1.13 — September 2019

Pool from the sync package has been improved so the pools are not cleared when the garbage collector runs. It introduced a cache to clean instances in pools that have not been used during two garbage collections.

The escape analysis was re-written and now allows the Go program to reduce the number of allocations on the heap. Here is a benchmark of this new escape analysis:

A Journey With Go

A Journey With Go Language Programming

Vincent Blanchon

Written by

French Gopher in Dubai

A Journey With Go

A Journey With Go Language Programming

Welcome to a place where words matter. On Medium, smart voices and original ideas take center stage - with no ads in sight. Watch
Follow all the topics you care about, and we’ll deliver the best stories for you to your homepage and inbox. Explore
Get unlimited access to the best stories on Medium — and support writers while you’re at it. Just $5/month. Upgrade