title: Go 1.24 Release Notes template: false

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 of 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 with GODEBUG setting gotestjsonbuildtext=1.

The new GOAUTH environment variable provides a flexible way to authenticate private module fetches. 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:

  • The benchmark function will execute exactly once per -count, so expensive setup and cleanup steps execute only once.
  • Function call parameters and results are kept alive, preventing the compiler from fully optimizing away the loop body.

New crypto/mlkem package

The new crypto/mlkem package implements ML-KEM-768 and ML-KEM-1024.

ML-KEM is a post-quantum key exchange mechanism formerly known as Kyber and specified in FIPS 203.

New crypto/hkdf, crypto/pbkdf2, and crypto/sha3 packages

The new crypto/hkdf package implements the HMAC-based Extract-and-Expand key derivation function HKDF, as defined in RFC 5869.

The new crypto/pbkdf2 package implements the password-based key derivation function PBKDF2, as defined in RFC 8018.

The new crypto/sha3 package implements the SHA-3 hash function and SHAKE and cSHAKE extendable-output functions, as defined in FIPS 202.

All three packages are based on pre-existing golang.org/x/crypto/... packages.

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.

  • The synctest.Run function starts a group of goroutines in an isolated “bubble”. Within the bubble, time package functions operate on a fake clock.
  • The synctest.Wait function waits for all goroutines in the current bubble to block.

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 {#minor_library_changes}

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:

  • Lines returns an iterator over the newline-terminated lines in the byte slice s.
  • SplitSeq returns an iterator over all substrings of s separated by sep.
  • SplitAfterSeq returns an iterator over substrings of s split after each instance of sep.
  • FieldsSeq returns an iterator over substrings of s split around runs of whitespace characters, as defined by unicode.IsSpace.
  • FieldsFuncSeq returns an iterator over substrings of s split around runs of Unicode code points satisfying f(c).

crypto/aes

The value returned by NewCipher no longer implements the NewCTR, NewGCM, NewCBCEncrypter, and NewCBCDecrypter methods. These methods were undocumented and not available on all architectures. Instead, the Block value should be passed directly to the relevant crypto/cipher functions. For now, crypto/cipher still checks for those methods on Block values, even if they are not used by the standard library anymore.

crypto/cipher

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

The Stream implementation returned by NewCTR when used with crypto/aes is now several times faster on amd64 and arm64.

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.

crypto/ecdsa

PrivateKey.Sign now produces a deterministic signature according to RFC 6979 if rand is nil.

crypto/md5

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

crypto/rand

The Read function is now guaranteed not to fail. It will always return nil as the error result. If Read were to encounter an error while reading from Reader, the program will irrecoverably crash. Note that the platform APIs used by the default Reader are documented to always succeed, so this change should only affect programs that override the Reader variable. One exception are Linux kernels before version 3.17, where the default Reader still opens /dev/urandom and may fail.

On Linux 6.11 and later, Reader now uses the getrandom vDSO. This is several times faster, especially for small reads.

On OpenBSD, Reader now uses arc4random_buf(3).

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. GODEBUG setting rsa1024min=0 restores the old behavior, but we recommend doing so only if necessary and only in tests, for example by adding a //go:debug rsa1024min=0 line to a test file. A new GenerateKey example provides an easy-to-use standard 2048-bit test key.

It is now safe and more efficient to call PrivateKey.Precompute before PrivateKey.Validate.

The package now rejects more invalid keys, and GenerateKey may return new errors for broken random sources. See also the changes to crypto/x509 below.

SignPKCS1v15 and VerifyPKCS1v15 now support SHA-512/224, SHA-512/256, and SHA-3.

Public and private key operations are now up to two times faster on wasm.

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 new 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. GODEBUG setting dataindependenttiming=1 enables the DIT mode for the entire Go program.

The XORBytes output must overlap exactly or not at all with the inputs. Previously, the behavior was otherwise undefined, while now XORBytes will panic.

crypto/tls

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

The new post-quantum X25519MLKEM768 key exchange mechanism is now supported and is enabled by default when Config.CurvePreferences is nil. GODEBUG setting tlsmlkem=0 reverts the default.

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.

The new ClientHelloInfo.Extensions field lists the IDs of the extensions received in the Client Hello message. This can be useful for fingerprinting TLS clients.

crypto/x509

The x509sha1 GODEBUG setting has been removed. Certificate.Verify no longer supports SHA-1 based signatures.

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 with GODEBUG setting 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 in RFC 5280 and RFC 9618. The new VerifyOptions.CertificatePolicies field can be set to an acceptable set of policy OIDs. 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 RSA keys that were previously accepted. Use GODEBUG setting x509rsacrt=0 to revert to recomputing the CRT values.

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:

  • File.DynamicVersionNeeds method returns a list of dynamic version needs in the ELF file, representing dependencies required by the executable.
  • File.DynamicVersions retrieves a list of dynamic versions defined in the ELF file.

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 use GODEBUG setting randseednop=0. For more background see 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:

  • NT AUTHORITY\SYSTEM
  • NT AUTHORITY\LOCAL SERVICE
  • NT AUTHORITY\NETWORK SERVICE

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:

  • Lines returns an iterator over the newline-terminated lines in the string s.
  • SplitSeq returns an iterator over all substrings of s separated by sep.
  • SplitAfterSeq returns an iterator over substrings of s split after each instance of sep.
  • FieldsSeq returns an iterator over substrings of s split around runs of whitespace characters, as defined by unicode.IsSpace.
  • FieldsFuncSeq returns an iterator over substrings of s split around runs of Unicode code points satisfying f(c).

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.