Go 1.19 Release Notes
Introduction to Go 1.19
The latest Go release, version 1.19, arrives five months after Go 1.18. Most of its changes are in the implementation of the toolchain, runtime, and libraries. As always, the release maintains the Go 1 promise of compatibility. We expect almost all Go programs to continue to compile and run as before.
Changes to the language
There is only one small change to the language, a very small correction to the scope of type parameters in method declarations. Existing programs are unaffected.
Memory Model
The Go memory model has been
revised to align Go with
the memory model used by C, C++, Java, JavaScript, Rust, and Swift.
Go only provides sequentially consistent atomics, not any of the more relaxed forms found in other languages.
Along with the memory model update,
Go 1.19 introduces new types in the sync/atomic package
that make it easier to use atomic values, such as
atomic.Int64
and
atomic.Pointer[T].
Ports
LoongArch 64-bit
Go 1.19 adds support for the Loongson 64-bit architecture
LoongArch
on Linux (GOOS=linux, GOARCH=loong64).
The implemented ABI is LP64D. Minimum kernel version supported is 5.19.
Note that most existing commercial Linux distributions for LoongArch come with older kernels, with a historical incompatible system call ABI. Compiled binaries will not work on these systems, even if statically linked. Users on such unsupported systems are limited to the distribution-provided Go package.
RISC-V
The riscv64 port now supports passing function arguments
and result using registers. Benchmarking shows typical performance
improvements of 10% or more on riscv64.
Tools
Doc Comments
Go 1.19 adds support for links, lists, and clearer headings in doc comments.
As part of this change, gofmt
now reformats doc comments to make their rendered meaning clearer.
See “Go Doc Comments”
for syntax details and descriptions of common mistakes now highlighted by gofmt.
As another part of this change, the new package go/doc/comment
provides parsing and reformatting of doc comments
as well as support for rendering them to HTML, Markdown, and text.
New unix build constraint
The build constraint unix is now recognized
in //go:build lines. The constraint is satisfied
if the target operating system, also known as GOOS, is
a Unix or Unix-like system. For the 1.19 release it is satisfied
if GOOS is one of
aix, android, darwin,
dragonfly, freebsd, hurd,
illumos, ios, linux,
netbsd, openbsd, or solaris.
In future releases the unix constraint may match
additional newly supported operating systems.
Go command
The -trimpath flag, if set, is now included in the build settings
stamped into Go binaries by go build, and can be
examined using
go version -m
or debug.ReadBuildInfo.
go generate now sets the GOROOT
environment variable explicitly in the generator’s environment, so that
generators can locate the correct GOROOT even if built
with -trimpath.
go test and go generate now place
GOROOT/bin at the beginning of the PATH used for the
subprocess, so tests and generators that execute the go command
will resolve it to same GOROOT.
go env now quotes entries that contain spaces in
the CGO_CFLAGS, CGO_CPPFLAGS, CGO_CXXFLAGS, CGO_FFLAGS, CGO_LDFLAGS,
and GOGCCFLAGS variables it reports.
go list -json now accepts a
comma-separated list of JSON fields to populate. If a list is specified,
the JSON output will include only those fields, and
go list may avoid work to compute fields that are
not included. In some cases, this may suppress errors that would otherwise
be reported.
The go command now caches information necessary to load some modules,
which should result in a speed-up of some go list invocations.
Vet
The vet checker “errorsas” now reports when
errors.As is called
with a second argument of type *error,
a common mistake.
Runtime
The runtime now includes support for a soft memory limit. This memory limit
includes the Go heap and all other memory managed by the runtime, and
excludes external memory sources such as mappings of the binary itself,
memory managed in other languages, and memory held by the operating system on
behalf of the Go program. This limit may be managed via
runtime/debug.SetMemoryLimit
or the equivalent
GOMEMLIMIT
environment variable. The limit works in conjunction with
runtime/debug.SetGCPercent
/ GOGC,
and will be respected even if GOGC=off, allowing Go programs to
always make maximal use of their memory limit, improving resource efficiency
in some cases. See the GC guide for
a detailed guide explaining the soft memory limit in more detail, as well as
a variety of common use-cases and scenarios. Please note that small memory
limits, on the order of tens of megabytes or less, are less likely to be
respected due to external latency factors, such as OS scheduling. See
issue 52433 for more details. Larger
memory limits, on the order of hundreds of megabytes or more, are stable and
production-ready.
In order to limit the effects of GC thrashing when the program’s live heap
size approaches the soft memory limit, the Go runtime also attempts to limit
total GC CPU utilization to 50%, excluding idle time, choosing to use more
memory over preventing application progress. In practice, we expect this limit
to only play a role in exceptional cases, and the new
runtime metric
/gc/limiter/last-enabled:gc-cycle reports when this last
occurred.
The runtime now schedules many fewer GC worker goroutines on idle operating system threads when the application is idle enough to force a periodic GC cycle.
The runtime will now allocate initial goroutine stacks based on the historic average stack usage of goroutines. This avoids some of the early stack growth and copying needed in the average case in exchange for at most 2x wasted space on below-average goroutines.
On Unix operating systems, Go programs that import package
os now automatically increase the open file limit
(RLIMIT_NOFILE) to the maximum allowed value;
that is, they change the soft limit to match the hard limit.
This corrects artificially low limits set on some systems for compatibility with very old C programs using the
select system call.
Go programs are not helped by that limit, and instead even simple programs like gofmt
often ran out of file descriptors on such systems when processing many files in parallel.
One impact of this change is that Go programs that in turn execute very old C programs in child processes
may run those programs with too high a limit.
This can be corrected by setting the hard limit before invoking the Go program.
Unrecoverable fatal errors (such as concurrent map writes, or unlock of
unlocked mutexes) now print a simpler traceback excluding runtime metadata
(equivalent to a fatal panic) unless GOTRACEBACK=system or
crash. Runtime-internal fatal error tracebacks always include
full metadata regardless of the value of GOTRACEBACK
Support for debugger-injected function calls has been added on ARM64, enabling users to call functions from their binary in an interactive debugging session when using a debugger that is updated to make use of this functionality.
The address sanitizer support added in Go 1.18 now handles function arguments and global variables more precisely.
Compiler
The compiler now uses
a jump
table to implement large integer and string switch statements.
Performance improvements for the switch statement vary but can be
on the order of 20% faster.
(GOARCH=amd64 and GOARCH=arm64 only)
The Go compiler now requires the -p=importpath flag to
build a linkable object file. This is already supplied by
the go command and by Bazel. Any other build systems
that invoke the Go compiler directly will need to make sure they
pass this flag as well.
The Go compiler no longer accepts the -importmap
flag. Build systems that invoke the Go compiler directly must use
the -importcfg flag instead.
Assembler
Like the compiler, the assembler now requires the