Go is a language that is often called simple and fast. But under the hood, it does a lot of magic, especially when it comes to working with memory. Understanding where and how data is stored can help you write more efficient code, avoid unnecessary allocations, and better understand program behavior.
Stack and heap: basics
Stack — memory that works on the LIFO (last in, first out) principle. Variables live until they exit the function. Working with the stack is fast and almost free.
Heap — memory area for objects whose lifetime cannot be determined in advance. It is managed by the garbage collector (GC). Allocations are more expensive, and assembly can slow down the program.
The main difference: on the stack, memory is freed automatically when exiting the function, and in the heap, GC monitors this.
Escape analysis: who escaped to the pile?
When the Go compiler encounters a variable, it decides where to store it — in a stack or a heap. This process is called escape analysis.
If the variable "escapes" outside the function, it is sent to the heap. If not, it remains in the stack.
Example 1. Local variable (remains in the stack)
func sum(a, b int) int {
c := a + b
return c
}
Example 2. The variable goes to the heap
func makePointer() *int {
x := 42
return &x
}
Here x returns by pointer. After exiting the function, the stack will be cleared and the value would be lost. Therefore, x "runs away" into the heap to continue living.

Checking escape analysis
go build -gcflags="-m" main.go
Example of output:
./main.go:5:6: moved to heap: x
When do variables run away in a heap?
Return from the function by pointer.
Stored in the closure.
Transmitted to the interface (sometimes).
The size of the structure is too large to fit on the stack.
Example 3. Closure
func adder() func(int) int {
sum := 0
return func(x int) int {
sum += x
return sum
}
}
Here sum is stored in the heap because it needs to live longer than the adder function.
Stack vs heap in practice
Characteristics | Stack | Pile |
|---|---|---|
Lifetime | While the function is running | Before GC assembly |
Access speed | Very fast | Slower |
Management | Automatic | Garbage collector |
Where are they stored | Local variables | Pointers, closures, long-lived objects |
How to write effective code
Avoid unnecessary pointers. The more indicators there are, the higher the chance of getting lost.
If possible, use values instead of links.
Keep an eye on escape analysis. Sometimes Go allocates memory in the heap, although it seems that it is not necessary.
Don't be afraid of the pile too much. Optimization is important, but premature optimization is evil.
Total
Understanding where data is stored in Go allows you to write more efficient code. Escape analysis is a tool that decides the fate of each variable. And knowing its rules, you can avoid unexpected brakes due to unnecessary allocations in the heap.
In Codice there is a full course on Go — from the basics to advanced topics. We analyze the syntax, work with memory, competitiveness and write mini-projects that will help consolidate knowledge.
And we also have an active Telegram channel, where we discuss cool ideas, share experiences and analyze tasks together — learning becomes not only useful, but also fun.
