Go 1.26 lands a faster linker and cleans up range-over-function

Link times on large binaries drop by roughly 35 percent, iterator functions get better error messages and inlining, and the garbage collector gains a tuning knob teams have asked for since 2019.

Younes Bekrar10 min read
ShareXLinkedInFacebook
Go 1.26 lands a faster linker and cleans up range-over-function

Go 1.26 shipped on Friday with a rewritten linker that cuts link time on large binaries by about 35 percent, which matters because linking had become the dominant cost in Go builds for anyone shipping a service with a few hundred dependencies. The release also improves range-over-function iterators, which arrived in 1.23 and have been widely adopted and widely complained about, with better inlining and error messages that name the actual problem. The garbage collector gains a soft memory target that can be adjusted at runtime, closing a request that has been open since 2019 and that every team running Go in containers has worked around badly.

The linker rewrite

Go's linker had been incrementally improved for a decade and retained a structure from a time when binaries were small and dependency counts were low. The 1.26 version parallelizes symbol resolution across cores, uses a compact intermediate representation that reduces memory pressure, and defers debug information generation until after the symbol table is final. On a 340 megabyte binary from a large internal service, link time in the Go team's benchmark fell from 8.4 seconds to 5.4.

example.ts
typescript
export async function handler(request: Request): Promise<Response> {  const started = Date.now();  const upstream = await fetch(request);  const headers = new Headers(upstream.headers);  headers.set("x-skarvonix-ms", String(Date.now() - started));  return new Response(upstream.body, {    status: upstream.status,    headers,  });}

Memory usage during linking dropped more dramatically, from 6.2 gigabytes to 2.8 on the same binary, which is the result CI operators will notice first. Builds that required a large runner class because the linker exhausted memory can move to a smaller instance. Several companies with large monorepos have been running the linker from the development branch since spring; Uber's Go platform team reported a 22 percent reduction in total build pipeline time attributable to this change alone.

Iterators grow up

Range-over-function let Go developers write custom iteration without exposing channels or index management, and the initial implementation had rough edges. Iterator functions were rarely inlined, which meant iterating a custom collection cost a function call per element and made the abstraction measurably slower than a hand-written loop. Go 1.26 inlines simple iterator functions, and benchmarks on a tree traversal show the gap against manual iteration closing from 40 percent to about 4.

The error messages also improved, which sounds minor and is not. Misusing an iterator previously produced a message about a function type mismatch that gave no hint about what was actually wrong, and the pattern of yield functions returning booleans is unintuitive enough that everyone gets it wrong initially. The compiler now recognizes the common mistakes and says what to fix. The standard library added iterator variants for several container operations in the slices and maps packages.

The story is rarely the launch. It is what breaks, what ships, and who owns the mess at 2 a.m.
Younes Bekrar

The garbage collector knob

Go's garbage collector has been tuned by GOGC, a percentage that controls how much heap growth triggers a collection, and by GOMEMLIMIT, a soft ceiling added in 1.19. Neither could be changed at runtime in a supported way, which is a problem for a process whose available memory changes, which describes every container in a cluster with vertical autoscaling.

Go 1.26 adds runtime functions to read and adjust both values, with the change taking effect at the next collection cycle. That lets a program respond to a cgroup limit change, which Kubernetes in-place pod resizing now makes routine. It also enables a pattern where a service raises its memory target during a traffic spike and lowers it afterward, trading collection frequency for latency in a controlled way. The runtime package documentation includes an example and a warning that adjusting these frequently produces unpredictable behavior.

Smaller changes worth knowing

The testing package gained a synctest facility for testing concurrent code with a controlled clock, which moves out of experimental status. That removes the sleep-based test patterns that make Go test suites flaky, and several projects have already converted. The net/http server added a configuration for per-connection request limits that helps with a class of resource exhaustion.

On the tooling side, go vet learned to detect a common mistake with iterator functions and a second one involving loop variable capture that the 1.22 semantics change mostly fixed. The module system now caches build lists more aggressively, cutting cold go build time on a large module by a few seconds. None of these individually matters and collectively they represent the steady quality work that has made Go's toolchain pleasant.

Upgrade risk

Go's compatibility promise means upgrades are usually uneventful, and this one should be. The linker rewrite is the largest risk surface, and it affects the build rather than the runtime, so problems surface immediately rather than in production. The Go team ran the new linker against a corpus of public modules and fixed the handful of issues that appeared, mostly involving unusual cgo configurations and one case with a very large number of exported symbols.

Teams using cgo heavily or linking against C++ should test before adopting in CI. Everyone else can upgrade on the usual schedule. The one behavioral change to watch is that binaries built with 1.26 are marginally larger, about 1.5 percent, because the new debug information layout trades size for generation speed. For most people that is irrelevant and for anyone shipping to constrained devices it is worth measuring.


Skarvonix will keep following this beat with reporting grounded in how systems behave outside the launch keynote.

  • Open Source

Keep reading