NOTE
3.2 Escape Analysis
How the Go compiler decides whether values can live in stack frames or must escape to longer-lived storage, how to inspect decisions, and why `new` does not imply heap allocation.
This is a historical learning note and may contain outdated or incomplete understanding.
1. What Is Escape Analysis?
In Go, source syntax does not directly determine stack versus heap allocation. The compiler analyzes object lifetimes and references and decides whether storage can safely remain associated with a stack frame or must escape to longer-lived storage.
This means:
new(T)does not imply “heap allocation”;- returning a pointer to a local variable is safe because the compiler/runtime gives the value an appropriate lifetime;
- a value may escape for reasons that are not obvious from one line of source code.
2. Why It Matters
Stack allocation is cheap and reclaimed with the goroutine stack. Heap allocation adds garbage-collector work and can increase memory traffic.
Escape analysis therefore supports both correctness and optimization.
3. Example
func value() *int {
x := 3
return &x
}
The returned pointer remains valid. The compiler sees that x outlives the function call and arranges storage accordingly.
4. Inspecting Compiler Decisions
Use compiler diagnostics rather than memorized rules:
go build -gcflags='-m=2' ./...
The output can show values moved to the heap, parameters that leak to results, inlining effects, and other escape decisions.
5. Avoid Over-Simplified Rules
“Referenced outside the function means heap; not referenced outside means stack” is only a learning shortcut. Real escape analysis also depends on:
- interface conversions;
- closures;
- captured variables;
- pointer flow through calls;
- object size and compiler constraints;
- inlining and compiler-version improvements.
Optimize allocations only after profiling. Forcing code into an unnatural shape to chase one escape diagnostic can make the program harder to maintain for negligible gain.