Lesson 24 · Senior Go backend engineering
Escape analysis: stack vs heap
Why some values stay cheap and others become GC work.
Your win: explain escape analysis in interview language, recognise the most common escape patterns, and connect heap allocation to the backend costs that actually matter: GC pressure, latency, and memory growth under load.
Why senior engineers care
At beginner level, it is enough to know that Go manages memory for you. At senior level, the next question is: what runtime work did my code create? Heap allocation is not a bug, but it usually means more work for the garbage collector — and on a busy service, that can show up as more memory use and more latency variance.
The two-memory story
Stack
Lives with the current call. Very cheap. Great for short-lived values that do not escape their frame.
Heap
Lives beyond one call when necessary. Flexible, but now the runtime must track and eventually reclaim it.
func good() int {
x := 42
return x // usually stays on the stack
}
func escaping() *int {
x := 42
return &x // pointer outlives the frame → heap escape
}
The common ways values escape
- Returning a pointer to a local value
- Capturing variables in closures
- Putting values into interface-shaped or heap-shaped data that outlives the current call
- Sending data into long-lived goroutines, queues, or shared structures
How to inspect it
go build -gcflags="-m" ./path/to/package
The compiler will print clues such as moved to heap. Read that output as a hint about runtime cost, not as an order to micro-optimize everything you see.
GC guide + diagnostics
The GC guide gives the big-picture cost model. The diagnostics docs help you observe what your code is actually doing on this machine today.
Check yourself (from memory)
Q1. A value usually escapes when…
Q2. Why do senior engineers care about escapes?
-gcflags="-m" output and a plain-English explanation of each escape? Ask me.
Sources. A Guide to the Go Garbage Collector; Go Diagnostics.