Go 1.25 Recap: Container-Aware by Default
GOMAXPROCS finally respects your container CPU limit, WaitGroup gets a Go method, and testing concurrent code gets a fake clock.
#golang #go-recap #kubernetes
Go recap series — one short post per release. Released August 2025.
TL;DR
GOMAXPROCSfollows your container CPU limit on Linux.wg.Go(func() { ... })replacesAdd(1)+defer Done().testing/synctesttests timeouts instantly with a fake clock.- Experiments to watch: Green Tea GC and JSON v2.
1. Container-aware GOMAXPROCS
The old problem: a Go app in a container limited to 2 CPUs, on a 64-core machine, used GOMAXPROCS=64. It tried to do 64 things at once with only 2 CPUs of quota — and got throttled.
What changed: on Linux, the default now respects the cgroup CPU limit (not the request). It also updates if the limit changes.
Why it matters: better latency in Kubernetes for free. You can usually remove automaxprocs.
2. sync.WaitGroup.Go
var wg sync.WaitGroup
for _, url := range urls {
wg.Go(func() {
fetch(url)
})
}
wg.Wait()
Why it matters: no forgotten Add or Done. go vet also warns about misplaced wg.Add now.
3. testing/synctest: a fake clock for tests
What changed: synctest.Test runs your test in a bubble with fake time. Time jumps forward when every goroutine is waiting.
func TestTimeout(t *testing.T) {
synctest.Test(t, func(t *testing.T) {
ctx, cancel := context.WithTimeout(t.Context(), 5*time.Second)
defer cancel()
time.Sleep(5 * time.Second) // returns instantly
synctest.Wait()
if ctx.Err() == nil {
t.Fatal("expected timeout")
}
})
}
Why it matters: a 5-second timeout test now takes milliseconds — and never flakes.
4. Worth knowing
- Green Tea GC (experiment): a new garbage collector. It becomes the default in 1.26.
encoding/json/v2(experiment): faster decoding. It backsencoding/jsonin 1.27.trace.FlightRecorder: keeps the last few seconds of trace in memory, so you can save it right after a problem.
Previous: ← Go 1.24 Recap · Next: Go 1.26 Recap →
Source: Go 1.25 release notes
