— notes
Go Pointers and Memory Management
On this page
When I first started learning Go, I was intrigued by its approach to memory management. Go handles memory in a way that’s both efficient and safe, but it can be a bit of a black box if you don’t peek under the hood.
Understanding Stack and Heap Memory
graph TD
subgraph STACK["Goroutine Stack"]
S1["Local variables"]
S2["Function parameters"]
S3["Return addresses"]
end
subgraph HEAP["Shared Heap"]
H1["Escaped variables"]
H2["Pointers returned\nfrom functions"]
H3["Closure captures"]
end
EA{{"Escape Analysis\n(compile time)"}}
EA -- "does not escape" --> STACK
EA -- "escapes to heap" --> HEAPPassing by Value: The Default Behavior
In Go, when you pass variables like integer, string, or boolean to a function, they are passed by value. A copy is made.
func increment(num int) {
num++
}
func main() {
n := 21
increment(n)
fmt.Println(n) // 21
}Introducing Pointers
To modify the original variable inside a function, pass a pointer.
func incrementPointer(num *int) {
(*num)++
}
func main() {
n := 42
incrementPointer(&n)
fmt.Println(n) // 43
}Escape Analysis
Escape analysis determines whether variables need to live beyond their function scope.
flowchart TD
A["Variable declared"] --> B{"Returned as\npointer?"}
B -- Yes --> HEAP["Allocate on Heap"]
B -- No --> C{"Captured by\nclosure?"}
C -- Yes --> HEAP
C -- No --> D{"Assigned to\ninterface?"}
D -- Yes --> HEAP
D -- No --> E{"Too large\nfor stack?"}
E -- Yes --> HEAP
E -- No --> STACK["Allocate on Stack"]Run go build -gcflags '-m' on any Go file to see escape analysis decisions.
Concurrency Issues – Data Race
func main() {
var wg sync.WaitGroup
counter := 0
counterPtr := &counter
for i := 0; i < 1000; i++ {
wg.Add(1)
go func() {
*counterPtr++
wg.Done()
}()
}
wg.Wait()
fmt.Println("Counter:", *counterPtr)
}This has a data race. Fix with a mutex:
var mu sync.Mutex
go func() {
mu.Lock()
*counterPtr++
mu.Unlock()
wg.Done()
}()Key Takeaways
- Passing by value is simple but can be inefficient for large data structures
- Using pointers avoids copying but requires synchronization for shared access
- Escape analysis determines stack vs heap allocation
- Go prevents dangling pointers via garbage collection
- Run
go test -raceto detect data races