Go 1.24 Release Notes

DRAFT RELEASE NOTES — Introduction to Go 1.24

Go 1.24 is not yet released. These are work-in-progress release notes. Go 1.24 is expected to be released in February 2025.

Changes to the language

Go 1.24 now fully supports generic type aliases: a type alias may be parameterized like a defined type. See the language spec for details. For now, the feature can be disabled by setting GOEXPERIMENT=noaliastypeparams; but the aliastypeparams setting will be removed for Go 1.25.

Tools

Go command

Go modules can now track executable dependencies using tool directives in go.mod. This removes the need for the previous workaround of adding tools as blank imports to a file conventionally named “tools.go”. The go tool command can now run these tools in addition to tools shipped with the Go distribution. For more information see the documentation.

The new -tool flag for go get causes a tool directive to be added to the current module for named packages in addition to adding require directives.

The new tool meta-pattern refers to all tools in the current module. This can be used to upgrade them all with go get -u tool or to install them into your GOBIN directory with go install tool.

Executables created by go run and the new behavior for go tool are now cached in the Go build cache. This makes repeated executions faster at the expense of making the cache larger. See #69290.

The go build and go install commands now accept a -json flag that reports build output and failures as structured JSON output on standard output. For details of the reporting format, see go help buildjson.

Furthermore, go test -json now reports build output and failures in JSON, interleaved with test result JSON. These are distinguished by new Action types, but if they cause problems in a test integration system, you can revert to the text build output by setting GODEBUG=gotestjsonbuildtext=1.

The new GOAUTH environment variable provides a flexible way to authenticate with private modules. See go help goauth for more information.

The go build command now includes versioning information in the compiled binary. If a local VCS tag is available, the main module’s version will be set from that tag. If no local VCS tag is available, a pseudo-version will be generated. A +dirty suffix will be appended if there are uncommitted VCS changes present. Use the -buildvcs=false flag to omit version control information from the binary.

The new GODEBUG setting toolchaintrace=1 can be used to trace the go command’s toolchain selection process.

Cgo

Cgo supports new annotations for C functions to improve run time performance. #cgo noescape cFunctionName tells the compiler that memory passed to the C function cFunctionname does not escape. #cgo nocallback cFunctionName tells the compiler that the C function cFunctionName does not call back to any Go functions. For more information, see the cgo documentation.

Cgo currently refuses to compile calls to a C function which has multiple incompatible declarations. For instance, if f is declared as both void f(int) and void f(double), cgo will report an error instead of possibly generating an incorrect call sequence for f(0). New in this release is a better detector for this error condition when the incompatible declarations appear in different files. See #67699.

Vet

The new tests analyzer reports common mistakes in declarations of tests, fuzzers, benchmarks, and examples in test packages, such as malformed names, incorrect signatures, or examples that document non-existent identifiers. Some of these mistakes may cause tests not to run. This analyzer is among the subset of analyzers that are run by go test.

The existing printf analyzer now reports a diagnostic for calls of the form fmt.Printf(s), where s is a non-constant format string, with no other arguments. Such calls are nearly always a mistake as the value of s may contain the % symbol; use fmt.Print instead. See #60529.

The existing buildtag analyzer now reports a diagnostic when there is an invalid Go major version build constraint within a //go:build directive. For example, //go:build go1.23.1 refers to a point release; use //go:build go1.23 instead. See #64127.

The existing copylock analyzer now reports a diagnostic when a variable declared in a 3-clause “for” loop such as for i := iter(); done(i); i = next(i) { ... } contains a sync.Locker, such as a sync.Mutex. Go 1.22 changed the behavior of these loops to create a new variable for each iteration, copying the value from the previous iteration; this copy operation is not safe for locks. See #66387.

GOCACHEPROG

The cmd/go internal binary and test caching mechanism can now be implemented by child processes implementing a JSON protocol between the cmd/go tool and the child process named by the GOCACHEPROG environment variable. This was previously behind a GOEXPERIMENT. For protocol details, see #59719.

Runtime

Several performance improvements to the runtime have decreased CPU overheads by 2—3% on average across a suite of representative benchmarks. Results may vary by application. These improvements include a new builtin map implementation based on Swiss Tables, more efficient memory allocation of small objects, and a new runtime-internal mutex implementation.

The new builtin map implementation and new runtime-internal mutex may be disabled by setting GOEXPERIMENT=noswissmap and GOEXPERIMENT=nospinbitmutex at build time respectively.

The new AddCleanup function attaches a cleanup function to a pointer. Once the object that the pointer points to is no longer reachable, the runtime will call the function. AddCleanup is a finalization mechanism that is more flexible and less error-prone than SetFinalizer. Unlike SetFinalizer, it does not resurrect the object it is attached to for finalization and multiple cleanups may be attached to a single object. New code should prefer AddCleanup over SetFinalizer.

Compiler

The compiler already disallowed defining new methods with receiver types that were cgo-generated, but it was possible to circumvent that restriction via an alias type. Go 1.24 now always reports an error if a receiver denotes a cgo-generated type, whether directly or indirectly (through an alias type).

Linker

The linker now generates a GNU build ID (the ELF NT_GNU_BUILD_ID note) on ELF platforms and a UUID (the Mach-O LC_UUID load command) on macOS by default. The build ID or UUID is derived from the Go build ID. It can be disabled by the -B none linker flag, or overridden by the -B 0xNNNN linker flag with a user-specified hexadecimal value.

Bootstrap

As mentioned in the Go 1.22 release notes, Go 1.24 now requires Go 1.22.6 or later for bootstrap. We expect that Go 1.26 will require a point release of Go 1.24 or later for bootstrap.

Standard library

Directory-limited filesystem access

The new os.Root type provides the ability to perform filesystem operations within a specific directory.

The os.OpenRoot function opens a directory and returns an os.Root. Methods on os.Root operate within the directory and do not permit paths that refer to locations outside the directory, including ones that follow symbolic links out of the directory.

New benchmark function

Benchmarks may now use the faster and less error-prone testing.B.Loop method to perform benchmark iterations like for b.Loop() { ... } in place of the typical loop structures involving b.N like for range b.N. This offers two significant advantages:

New crypto/hkdf package

The new crypto/hkdf package implements the HMAC-based Extract-and-Expand Key Derivation Function (HKDF) as defined in RFC 5869. It is based on the pre-existing golang.org/x/crypto/hkdf package.

New crypto/mlkem package

The new crypto/mlkem package implements ML-KEM (formerly known as Kyber), as specified in NIST FIPS 203.

New crypto/pbkdf2 package

The new crypto/pbkdf2 package implements the key derivation function PBKDF2 as defined in RFC 2898 / PKCS #5 v2.0. It is based on the pre-existing golang.org/x/crypto/pbkdf2 package.

New crypto/sha3 package

The new crypto/sha3 package implements the SHA-3 hash function, and SHAKE and cSHAKE extendable-output functions. It is based on the pre-existing golang.org/x/crypto/sha3 package.

New weak package

The new weak package provides weak pointers.

Weak pointers are a low-level primitive provided to enable the creation of memory-efficient structures, such as weak maps for associating values, canonicalization maps for anything not covered by package unique, and various kinds of caches. For supporting these use-cases, this release also provides runtime.AddCleanup and maphash.Comparable.

New experimental testing/synctest package

The new experimental testing/synctest package provides support for testing concurrent code.

See the package documentation for more details.

The synctest package is experimental and must be enabled by setting GOEXPERIMENT=synctest at build time. The package API is subject to change in future releases. See issue #67434 for more information and to provide feeback.

Minor changes to the library

archive

The (*Writer).AddFS implementations in both archive/zip and archive/tar now write a directory header for an empty directory.

bytes

The bytes package adds several functions that work with iterators:

crypto/cipher

NewOFB, NewCFBEncrypter, and NewCFBDecrypter are now deprecated. OFB and CFB mode are not authenticated, which generally enables active attacks to manipulate and recover the plaintext. It is recommended that applications use AEAD modes instead. If an unauthenticated Stream mode is required, use NewCTR instead.

The new NewGCMWithRandomNonce function returns an AEAD that implements AES-GCM by generating a random nonce during Seal and prepending it to the ciphertext.

crypto/fips140

TODO: FIPS 140 will be covered in its own section. TODO: accepted proposal #70200 (from CL 629196, CL 629198, CL 629201, CL 629996)

crypto/md5

The value returned by md5.New now also implements the encoding.BinaryAppender interface.

crypto/rand

The Read function, and the Read method of Reader, are now defined to never fail. They will always return nil as the error result. If something somehow goes wrong while reading random numbers, the program will irrecoverably crash. This change was made because all supported systems now provide sources of random bytes that never fail.

The new Text function can be used to generate cryptographically secure random text strings.

crypto/rsa

GenerateKey now returns an error if a key of less than 1024 bits is requested. All Sign, Verify, Encrypt, and Decrypt methods now return an error if used with a key smaller than 1024 bits. Such keys are insecure and should not be used. Setting GODEBUG=rsa1024min=0 or including //go:debug rsa1024min=0 in a source file restores the old behavior, but we recommend doing so only in tests, if necessary. A new GenerateKey example provides an easy-to-use standard 2048-bit test key.

crypto/sha1

The value returned by sha1.New now also implements the encoding.BinaryAppender interface.

crypto/sha256

The values returned by sha256.New and sha256.New224 now also implement the encoding.BinaryAppender interface

crypto/sha512

The values returned by sha512.New, sha512.New384, sha512.New512_224 and sha512.New512_256 now also implement the encoding.BinaryAppender interface.

crypto/subtle

The WithDataIndependentTiming function allows the user to run a function with architecture specific features enabled which guarantee specific instructions are data value timing invariant. This can be used to make sure that code designed to run in constant time is not optimized by CPU-level features such that it operates in variable time. Currently, WithDataIndependentTiming uses the PSTATE.DIT bit on arm64, and is a no-op on all other architectures.

crypto/tls

The ClientHelloInfo struct passed to Config.GetCertificate now includes an Extensions field, which can be useful for fingerprinting TLS clients.

The TLS server now supports Encrypted Client Hello (ECH). This feature can be enabled by populating the Config.EncryptedClientHelloKeys field.

crypto/tls now supports the post-quantum X25519MLKEM768 key exchange. Support for the experimental X25519Kyber768Draft00 key exchange has been removed.

Key exchange ordering is now handled entirely by the crypto/tls package. The order of Config.CurvePreferences is now ignored, and the contents are only used to determine which key exchanges to enable when the field is populated.

crypto/x509

The x509sha1 GODEBUG setting has been removed. Certificate.Verify will no longer consider SHA-1 based signatures valid when this GODEBUG setting is set.

OID now implements the encoding.BinaryAppender and encoding.TextAppender interfaces.

The default certificate policies field has changed from Certificate.PolicyIdentifiers to Certificate.Policies. When parsing certificates, both fields will be populated, but when creating certificates policies will now be taken from the Certificate.Policies field instead of the [Certificate.PolicyIdentifiers field]. This change can be reverted by setting GODEBUG=x509usepolicies=0.

CreateCertificate will now generate a serial number using a RFC 5280 compliant method when passed a template with a nil Certificate.SerialNumber field, instead of failing.

Certificate.Verify now supports policy validation, as defined by RFC 5280 and RFC 9618. In order to enable policy validation, VerifyOptions.CertificatePolicies must be set to an acceptable set of policy OIDs. When enabled, only certificate chains with valid policy graphs will be returned from Certificate.Verify.

MarshalPKCS8PrivateKey now returns an error instead of marshaling an invalid RSA key. (MarshalPKCS1PrivateKey doesn’t have an error return, and its behavior when provided invalid keys continues to be undefined.)

ParsePKCS1PrivateKey and ParsePKCS8PrivateKey now use and validate the encoded CRT values, so might reject invalid keys that were previously accepted. Use GODEBUG=x509rsacrt=0 to revert to recomputing them.

debug/elf

The debug/elf package adds several new constants, types, and methods to add support for handling dynamic versions and version flags in ELF (Executable and Linkable Format) files:

Several new types have been introduced:

The following methods have been added:

encoding

Two new interfaces, TextAppender and BinaryAppender, have been introduced to append the textual or binary representation of an object to a byte slice. These interfaces provide the same functionality as TextMarshaler and BinaryMarshaler, but instead of allocating a new slice each time, they append the data directly to an existing slice.

encoding/json

When marshaling, a struct field with the new omitzero option in the struct field tag will be omitted if its value is zero. If the field type has an IsZero() bool method, that will be used to determine whether the value is zero. Otherwise, the value is zero if it is the zero value for its type.

If both omitempty and omitzero are specified, the field will be omitted if the value is either empty or zero (or both).

UnmarshalTypeError.Field now includes embedded structs to provide more detailed error messages.

go/types

All go/types data structures that expose sequences using a pair of methods such as Len() int and At(int) T now also have methods that return iterators, allowing you to simplify code such as this:

params := fn.Type.(*types.Signature).Params()
for i := 0; i < params.Len(); i++ {
   use(params.At(i))
}

to this:

for param := range fn.Signature().Params().Variables() {
   use(param)
}

The methods are: Interface.EmbeddedTypes, Interface.ExplicitMethods, Interface.Methods, MethodSet.Methods, Named.Methods, Scope.Children, Struct.Fields, Tuple.Variables, TypeList.Types, TypeParamList.TypeParams, Union.Terms.

hash/adler32

The value returned by New now also implements the encoding.BinaryAppender interface.

hash/crc32

The values returned by New and NewIEEE now also implement the encoding.BinaryAppender interface.

hash/crc64

The value returned by New now also implements the encoding.BinaryAppender interface.

hash/fnv

The values returned by New32, New32a, New64, New64a, New128 and New128a now also implement the encoding.BinaryAppender interface.

hash/maphash

New function Comparable returns the hash of a comparable value. New function WriteComparable adds a comparable value to the data hashed by a Hash.

log/slog

The new DiscardHandler is a handler that is never enabled and always discards its output.

Level and LevelVar now implement the encoding.TextAppender interface.

math/big

Float, Int and Rat now implement the encoding.TextAppender interface.

math/rand

Calls to the deprecated top-level Seed function no longer have any effect. To restore the old behavior set GODEBUG=randseednop=0. For more background see the proposal #67273.

math/rand/v2

ChaCha8 and PCG now implement the encoding.BinaryAppender interface.

net

ListenConfig now uses MPTCP by default on systems where it is supported (currently on Linux only).

IP now implements the encoding.TextAppender interface.

net/http

Transport’s limit on 1xx informational responses received in response to a request has changed. It previously aborted a request and returned an error after receiving more than 5 1xx responses. It now returns an error if the total size of all 1xx responses exceeds the Transport.MaxResponseHeaderBytes configuration setting.

In addition, when a request has a net/http/httptrace.ClientTrace.Got1xxResponse trace hook, there is now no limit on the total number of 1xx responses. The Got1xxResponse hook may return an error to abort a request.

Transport and Server now have an HTTP2 field which permits configuring HTTP/2 protocol settings.

The new Server.Protocols and Transport.Protocols fields provide a simple way to configure what HTTP protocols a server or client use.

The server and client may be configured to support unencrypted HTTP/2 connections.

When Server.Protocols contains UnencryptedHTTP2, the server will accept HTTP/2 connections on unencrypted ports. The server can accept both HTTP/1 and unencrypted HTTP/2 on the same port.

When Transport.Protocols contains UnencryptedHTTP2 and does not contain HTTP1, the transport will use unencrypted HTTP/2 for http:// URLs. If the transport is configured to use both HTTP/1 and unencrypted HTTP/2, it will use HTTP/1.

Unencrypted HTTP/2 support uses “HTTP/2 with Prior Knowledge” (RFC 9113, section 3.3). The deprecated “Upgrade: h2c” header is not supported.

net/netip

Addr, AddrPort and Prefix now implement the encoding.BinaryAppender and encoding.TextAppender interfaces.

net/url

URL now also implements the encoding.BinaryAppender interface.

os/user

On Windows, Current can now be used in Windows Nano Server. The implementation has been updated to avoid using functions from the NetApi32 library, which is not available in Nano Server.

On Windows, Current, Lookup and LookupId now support the following built-in service user accounts:

On Windows, Current has been made considerably faster when the current user is joined to a slow domain, which is the usual case for many corporate users. The new implementation performance is now in the order of milliseconds, compared to the previous implementation which could take several seconds, or even minutes, to complete.

On Windows, Current now returns the process owner user when the current thread is impersonating another user. Previously, it returned an error.

regexp

Regexp now implements the encoding.TextAppender interface.

runtime

The GOROOT function is now deprecated. In new code prefer to use the system path to locate the “go” binary, and use go env GOROOT to find its GOROOT.

strings

The strings package adds several functions that work with iterators:

sync

The implementation of sync.Map has been changed, improving overall performance and resolving some long-standing issues. If you encounter any problems, set GOEXPERIMENT=nosynchashtriemap at build time to switch back to the old implementation and please file an issue.

testing

The new T.Context and B.Context methods return a context that’s canceled after the test completes and before test cleanup functions run.

The new T.Chdir and B.Chdir methods can be used to change the working directory for the duration of a test or benchmark.

text/template

Templates now support range-over-func and range-over-int.

time

Time now implements the encoding.BinaryAppender and encoding.TextAppender interfaces.

Ports

Linux

As announced in the Go 1.23 release notes, Go 1.24 requires Linux kernel version 3.2 or later.

Darwin

Go 1.24 is the last release that will run on macOS 11 Big Sur. Go 1.25 will require macOS 12 Monterey or later.

WebAssembly

The go:wasmexport directive is added for Go programs to export functions to the WebAssembly host.

On WebAssembly System Interface Preview 1 (GOOS=wasip1, GOARCH=wasm), Go 1.24 supports building a Go program as a reactor/library, by specifying the -buildmode=c-shared build flag.

More types are now permitted as argument or result types for go:wasmimport functions. Specifically, bool, string, uintptr, and pointers to certain types are allowed (see the proposal for detail), along with 32-bit and 64-bit integer and float types, and unsafe.Pointer, which are already allowed. These types are also permitted as argument or result types for go:wasmexport functions.

The support files for WebAssembly have been moved to lib/wasm from misc/wasm.

Windows

The windows/arm port (GOOS=windows GOARCH=arm) has been marked broken. See issue #70705 for details.