Go 1.19 focuses on improving the implementation of the toolchain, runtime, and libraries, especially for generics performance, the language memory model, and garbage collection.
After the introduction of generics in Go 1.18, the Go team has been working on improving their implementation to increase performance and to address subtle syntax corner cases. Generics performance can be up to 20% higher in some programs, says the Go team, although no benchmarks have been released yet. The syntax correction affects the scope of function type parameters, which makes it possible to write declarations like the following:
type T[T any] struct {}
func (T[T]) m() {}
In Go 1.18, instead, the T
inside the [T]
function parameter is shadowed by the outer type
definition, producing an error.
The Go memory model, which defines the way Go ensures variables read in one goroutine are guaranteed to reflect values written to that variable in a different goroutine, has been revised introducing a new definition of the happen-before relation which brings its semantics closer to that of other mainstream languages, including C, C++, Java, Rust, and Swift. This change does not impact existing programs, says Google, and should not concern most developers. In addition, a couple of new atomic types have been added to the sync/atomic
package, specifically atomic.Int64
and atomic.Pointer[T]
, mostly to simplify their usage.
Go 1.19 also introduces a few changes to its garbage collector that should help optimize Go programs so they run more efficiently in containers with dedicated amounts of memory.
Until Go 1.19, GOGC was the sole parameter that could be used to modify the GC's behavior. While it works great as a way to set a trade-off, it doesn't take into account that available memory is finite.
In particular, the possibility of transient spikes, which require new memory allocation proportional to the live heap, pose a limit to the maximum value that can be set for the live heap size (GOGC). For example, if the transient spike requires a new heap of the same size as the live heap, GOGC must be set to half the available memory, even if an higher value could provide better performance.
To better handle this, Go 1.19 introduces a configurable memory limit, controlled through the GOMEMLIMIT
environment variable. Knowing the maximum heap size, the Go garbage collector can set the total heap size in a more efficient way.
As a last note, Go 1.19 introduces a number of performance and implementation improvements including dynamic sizing of initial goroutine stacks, automatic use of additional Unix file descriptors, jump tables for large switch statements on x86-64 and ARM64, and many others. If you are interested in the full details, make sure you read the official release notes.