What Is New in Go 1.26
| Category | Highlights |
|---|---|
| New Features |
|
| Improvements |
|
| Breaking Changes |
|
| Deprecations |
|
What does the Green Tea garbage collector change in Go 1.26?
The Green Tea garbage collector, previously an opt-in experiment in Go 1.25, is now the default GC in Go 1.26 and represents the most impactful runtime change in this release. It improves marking and scanning of small objects through better CPU locality and scalability, targeting the workloads where Go programs spend the most GC time.
Benchmark results vary by workload, but teams running GC-heavy services should expect somewhere between a 10--40% reduction in garbage collection overhead. On newer amd64 platforms (Intel Ice Lake, AMD Zen 4 and later), the GC also leverages vector instructions for scanning small objects, delivering an additional ~10% improvement on top of that baseline.
In practice, the transition should be transparent. If you hit regressions -- particularly around memory layout assumptions or tight latency budgets -- you can disable the new GC at build time:
GOEXPERIMENT=nogreenteagc go build ./...
Watch out for this opt-out being removed in Go 1.27. If you need to disable it, file a bug with the Go team now so it can be addressed before the window closes.
How does Go 1.26 improve security for programs using cgo?
Go 1.26 introduces heap base address randomization on 64-bit platforms, making it significantly harder for attackers to predict memory layouts and exploit memory safety issues in cgo-enabled code. This runs automatically at startup with no code changes required.
On top of that, cgo call overhead itself has been cut by approximately 30% at the baseline. For services with tight hot paths that must cross the Go/C boundary -- think embedded databases, GPU bindings, or OS-level integrations -- this is a meaningful free win.
Additionally, the crypto/subtle.WithDataIndependentTiming function now propagates timing isolation to spawned goroutines and their descendants, and correctly carries that state across cgo call boundaries in both directions. Most teams doing side-channel-sensitive crypto work will want to verify their isolation boundaries cover the full goroutine tree.
What cryptography changes landed in Go 1.26 and do they require migration?
Go 1.26 ships a significant batch of crypto improvements, most of which are backward-compatible but a few of which carry migration implications. The biggest headline is the new crypto/hpke package, a production-ready implementation of Hybrid Public Key Encryption (RFC 9180) including post-quantum hybrid KEMs -- useful for any teams building forward-secret key exchange into their protocols.
Post-quantum key exchange is also now on by default in crypto/tls: SecP256r1MLKEM768 and SecP384r1MLKEM1024 are enabled automatically. Most TLS stacks will just pick this up. You can disable it with Config.CurvePreferences or the tlssecpmlkem=0 GODEBUG if you need to target clients that choke on larger key exchange payloads.
The deeper migration concern is the crypto random parameter changes. Across crypto/rsa, crypto/ecdsa, crypto/ecdh, crypto/dsa, and crypto/rand, the rand io.Reader parameter passed to key generation and signing functions is now silently ignored -- the runtime always uses its own secure random source. If your test suite injects a deterministic rand for reproducibility, that approach no longer works. Migrate to testing/cryptotest.SetGlobalRandom instead.
import "testing/cryptotest"
func TestKeyGeneration(t *testing.T) {
cryptotest.SetGlobalRandom(t, deterministicReader)
key, err := rsa.GenerateKey(nil, 2048) // rand param ignored; SetGlobalRandom takes effect
// ...
}
How does the revamped go fix command work in Go 1.26?
The go fix command has been completely rewritten in Go 1.26 and is now a fully automated code modernization framework -- not just a handful of one-off migration scripts. It is built on the same analysis framework as go vet, which means its fixers are reliable, composable, and auditable in the same way diagnostics are.
The initial release ships dozens of fixers that update code to use modern language and standard library features. You can also write your own automated API migrations using //go:fix inline directives on functions you want inlined away, enabling a clean deprecation-and-migration workflow for library authors.
# Apply all available modernizers to your module
go fix ./...
# Preview what would change without applying
go fix -list ./...
This matters especially if you maintain a large codebase that has accumulated pre-generics patterns, old io/ioutil calls, or other idioms that newer Go versions supersede. The old historical fixers (which were already obsolete) have been removed.
What new language features does Go 1.26 introduce?
Go 1.26 adds two notable language changes. First, the built-in new function now accepts an initializer expression, not just a type. This removes an awkward pattern that anyone working with pointer-optional fields in JSON or protobuf structs will recognize immediately.
Before Go 1.26, initializing a pointer field inline required a helper function or a separate variable. Now you can write this directly:
type Person struct {
Name string `json:"name"`
Age *int `json:"age"` // optional
}
// Old approach: required a helper or temp variable
age := yearsSince(born)
p := Person{Name: name, Age: &age}
// Go 1.26: initialize inline
p := Person{
Name: name,
Age: new(yearsSince(born)),
}
Second, generic types can now reference themselves in their own type parameter constraints. This was previously rejected by the compiler and limited the expressiveness of recursive type hierarchies. A type like Adder[A Adder[A]] -- where an interface requires that implementors be combinable with themselves -- is now valid. In practice, this unlocks cleaner algebra-style interfaces and simplifies some functional programming patterns in Go.
Frequently Asked Questions -- Go 1.26
Do I need to change my code to benefit from the Green Tea garbage collector in Go 1.26?
No code changes are required. The new GC is enabled by default when you build with Go 1.26, and you can disable it with GOEXPERIMENT=nogreenteagc at build time if needed.
Will existing crypto code break because the rand parameter is now ignored in Go 1.26?
Production code will generally continue to work unchanged since it typically passes crypto/rand.Reader which the runtime was already using. The main impact is on tests that inject deterministic readers for reproducibility -- those tests need to be migrated to use testing/cryptotest.SetGlobalRandom instead. The GODEBUG setting cryptocustomrand=1 restores the old behavior as a temporary bridge.
Is the ReverseProxy.Director field removed in Go 1.26?
No, Director is deprecated but not removed in Go 1.26. It still works, but you should migrate to ReverseProxy.Rewrite because Director is fundamentally unsafe -- a malicious client can remove headers added by a Director function by designating them as hop-by-hop, and there is no fix possible within the Director API design.
What happens to go tool doc in Go 1.26?
The cmd/doc binary and go tool doc subcommand have been deleted. Use go doc as a drop-in replacement -- it accepts the same flags and arguments and behaves identically.
Does the goroutine leak profiler add overhead to production services in Go 1.26?
No. The experimental goroutine leak profile is designed to incur zero additional runtime overhead unless it is actively being sampled, making it safe to enable in production builds.
Does upgrading to Go 1.26 change the go version written into new go.mod files?
Yes. Running go mod init with Go 1.26 now writes go 1.25.0 into new go.mod files instead of the current toolchain version, which encourages creating modules compatible with the two currently supported Go releases. You can follow up with go get go@version to pin a specific version if your module requires a different minimum.