Go 1.26: Language Changes, Green Tea GC and more
Hey everyone!
Go 1.26 was released in February 2026, six months after version 1.25. The release brings updates to the language specification, runtime behavior, and development toolchain.
The main highlight is the default activation of the Green Tea garbage collector, which focuses on memory locality. Below are the key changes detailed by component.
What you will find here
This version introduces updates in four main areas:
- Language changes:
newsupporting expression operands and self-referencing generic type parameters. - New garbage collector: Green Tea GC enabled by default.
- Tools: refactoring of the
go fixcommand to support modernizers. - Standard library: optimizations in
io, new iterators inreflect, and new cryptographic packages.
1. Language Changes
The new function accepts expressions as operands
The built-in new function now allows its argument to be an expression, defining the initial value of the allocated pointer.
This change reduces the boilerplate code required to reference pointers in optional struct fields, such as those used in JSON serialization or Protocol Buffers:
1
2
3
4
5
6
7
8
9
10
11
type Person struct {
Name string `json:"name"`
Age *int `json:"age"` // nil if omitted from payload
}
func personJSON(name string, born time.Time) ([]byte, error) {
return json.Marshal(Person{
Name: name,
Age: new(yearsSince(born)), // Direct allocation and initialization
})
}
Previously, the compiler required declaring a temporary variable to obtain the memory address:
1
2
3
// Pre-Go 1.26 approach
age := yearsSince(born)
person := Person{Name: name, Age: &age}
graph TD
subgraph "Before"
step1["Step 1: Create local var: age := 30"] --> step2["Step 2: Assign address: &age"]
end
subgraph "Go 1.26"
step3["Use new: new(30)"] --> step4["Returns pointer directly to the heap"]
end
Generics: self-referencing in type parameter lists
The restriction preventing a generic type from referencing itself in its own type parameter list has been removed. It is now possible to define type constraints that refer to the generic type being constrained:
1
2
3
4
5
6
7
type Adder[A Adder[A]] interface {
Add(A) A
}
func algo[A Adder[A]](x, y A) A {
return x.Add(y)
}
Before this release, declaring the Adder interface on the first line triggered a compilation error. This change simplifies the generics specification and supports more expressive constraints.
2. New Garbage Collector: Green Tea GC
Architecture of the Green Tea GC
The Green Tea garbage collector, previously available under an experimental flag in Go 1.25, is now the default collector.
Unlike the traditional algorithm, which performs scanning based on individual pointers scattered across memory (which can degrade cache locality), the Green Tea GC processes contiguous memory blocks and pages.
graph TD
subgraph "Traditional GC"
A1["Page 1: Object A"] -->|Cache Miss| B3["Page 3: Object B"]
B3 -->|Cache Miss| C2["Page 2: Object C"]
end
subgraph "Green Tea GC"
subgraph "Page 1"
D1["Object A"] --> D2["Object D"] --> D3["Object E"]
end
subgraph "Page 2"
E1["Object C"] --> E2["Object F"]
end
D3 -->|Sequential| E1
end
This approach enhances spatial locality and reduces marking and sweeping latency for small objects.
Performance Impact of the GC
The estimated reduction in GC overhead ranges from 10% to 40% in applications with high small-object allocation rates.
On modern CPUs that support vector instructions (such as Intel Ice Lake, AMD Zen 4, or newer), the runtime leverages vectorization to optimize object scanning, yielding an additional performance improvement of approximately 10%.
Disabling the Collector Temporarily
If you encounter performance regressions or unexpected behavior, the previous collector can be re-enabled using the GOEXPERIMENT flag at build time:
1
GOEXPERIMENT=nogreenteagc go build .
Compatibility Notice: The
nogreenteagcflag will be removed in Go 1.27. Any issues encountered with the new collector should be reported directly to the official Go issue tracker.
Runtime Optimizations
- CGO Invocations: The baseline runtime overhead for calling C functions via cgo has been reduced by approximately 30%.
- Heap Address Randomization: On 64-bit systems, the runtime now randomizes the heap base address at startup to mitigate security risks associated with pointer predictability.
- Goroutine Leak Profile (Experimental): A diagnostic profile designed to detect goroutines permanently blocked on channels, mutexes, or condition variables. It can be run with the following flag:
1
GOEXPERIMENT=goroutineleakprofile go build .
3. Tools: Rewritten go fix
The go fix utility has been restructured and now centralizes the execution of modernizers. These are static analysis tools that automate the migration of legacy codebases to modern syntax patterns and newer standard library APIs.
The rewritten tool uses the same analysis engine as go vet, enabling issues flagged by linters to be automatically resolved.
1
2
# Apply modernization rules to the project
go fix ./...
Modernizers apply refactorings that preserve the program’s original semantics. The tool also includes a source-level inliner activated by the //go:fix inline directive to help automate internal API deprecation migrations.
Other Toolchain Updates
- Default version in
go.mod: Thego mod initcommand now defaults to the previous minor version of Go (e.g., Go 1.26 initializes the file with thego 1.25.0directive), promoting backward compatibility. - Removal of
cmd/doc: The internal executablego tool dochas been deprecated. The standard commandgo docremains available with the same functionality. - Flame Graph defaults: The web interface of the
pproftool (started with the-httpflag) now displays the Flame Graph as the default view.
4. Standard Library
log/slog: MultiHandler
The structured logging package now includes the NewMultiHandler function, allowing log events to be dispatched to multiple destinations simultaneously without custom adapter implementations:
1
2
3
4
5
handler := slog.NewMultiHandler(
slog.NewJSONHandler(os.Stdout, nil),
slog.NewTextHandler(logFile, nil),
)
logger := slog.New(handler)
io: io.ReadAll Optimization
The implementation of io.ReadAll has been optimized to allocate smaller intermediate buffers and return slices sized exactly to the data read. The operation is up to twice as fast and reduces memory allocation by approximately 50% for medium to large payloads.
reflect: Iterators for Structs and Types
Aligning with the new support for range-over-functions (functional iterators), the reflect package introduces native iterators for fields and method signatures:
1
2
3
4
// Simplified iteration over struct fields
for field, value := range reflect.ValueOf(myStruct).Fields() {
fmt.Println(field.Name, value)
}
The new methods include Type.Fields, Type.Methods, Type.Ins, Type.Outs, Value.Fields, and Value.Methods.
testing: Artifact Directory
Tests, benchmarks, and fuzzing routines now support a designated directory for output files generated during test execution (such as screenshots, raw JSON data, or custom logs). These are exposed via T.ArtifactDir(), B.ArtifactDir(), and F.ArtifactDir() when passing the -artifacts flag:
1
go test -artifacts ./...
Summary of Key Changes
| Component | Change | Practical Impact |
|---|---|---|
| Runtime | Green Tea GC by default | 10% to 40% reduction in garbage collection overhead |
| Language | new with expressions | Simplified syntax for pointer allocation and initialization |
| Language | Self-referential generics | Flexibly defined generic type constraints |
| Tools | Modernizers in go fix | Automated refactoring to align with modern APIs |
| Runtime | CGO performance optimization | Approximately 30% lower overhead for C calls |
io | io.ReadAll optimization | Up to 2x faster execution with 50% fewer allocations |
| Platforms | Deprecation of macOS 12 | Go 1.27 will require macOS 13 Ventura or newer |
Conclusion
Go 1.26 consolidates performance improvements focused on memory efficiency, particularly through the Green Tea GC. The benefits are most noticeable in services with high small-object allocation rates.
Syntax enhancements simplify pointer patterns, and the rebuilt go fix command facilitates automated codebase maintenance. The release adheres to the Go 1 compatibility guarantee, ensuring existing code compiles without manual modifications.
Technical References
- Go 1.26 Release Notes - Official release documentation.
- Go Downloads - Official installation binaries for version 1.26.
- Green Tea GC Design - Technical proposal and discussion on the memory-block-centric collector.
- Go Modernizers Proposal - Details on the rewritten
go fixarchitecture. - Avoiding Premature Concurrency in Go - Insights on concurrency design and resource optimization.
