Go

List the common reasons a value escapes to the heap.

Question 333HardGo 1.22 to 1.25
  • Returning or storing its address somewhere that outlives the frame: a global, a heap object, or a channel send of a pointer.
  • Interface conversion, where a non-pointer value is boxed into any. fmt.Println(x) is the classic case. Small integers 0-255, zero values and constants can use static data and avoid the allocation.
  • Closures that capture variables by reference and outlive the frame, such as go func(){...}() or returned funcs.
  • Sizes unknown at compile time: make([]T, n) with a non-constant n. Go 1.25 can put small variable-sized backing arrays on the stack, but you should not rely on it.
  • Values that are too large. Explicitly declared variables over 128 KB, or implicit allocations (new, &T{}, make) over 64 KB, go to the heap. The explicit limit was 10 MB in older releases.
  • Calls the compiler cannot analyse: arguments passed through interface method calls or function values are assumed to escape.
  • Slices of pointers or maps whose elements are pointers to locals.
type Logger interface{ Log(v any) }

func work(l Logger) {
    buf := make([]byte, 64) // constant size, would stay on the stack...
    l.Log(buf)              // ...but a dynamic call through an interface makes buf escape
}

What the interviewer is looking for: interfaces and indirect calls are the most common hidden source of allocations in hot paths. You find them by profiling and reading -m output, not by guessing.

More on Memory, GC & Runtime Internals

All 38 Memory, GC & Runtime Internals questions