Exploring Heap Memory and Garbage Collector Algorithm in Go Language



This content originally appeared on DEV Community and was authored by Seyed Ahmad

Go automatically manages memory with the heap and a concurrent mark-and-sweep garbage collector.

Escape analysis decides whether variables live on the stack or heap.

GC uses a tricolor abstraction (white, gray, black) to track objects.

Runs concurrently with goroutines using write barriers to stay consistent.

You can tune performance with GOGC, GOMEMLIMIT, and SetMemoryLimit.

Result: less manual memory management, better scalability, and predictable performance. 🚀

Exploring Heap Memory and Garbage Collection in Go

Memory management is a critical part of building scalable applications. Go takes care of this for developers by automatically allocating memory on the heap and reclaiming unused objects through its garbage collector (GC). Unlike many other languages, Go’s GC is concurrent, non-generational, and non-compacting, designed to reduce pause times and keep applications responsive.

🔹 Heap Memory in Go

Dynamic Allocation

The heap is where Go stores data that cannot be determined at compile time or whose size is dynamic—such as slices, maps, and objects that escape the current function scope.

Escape Analysis

Before deciding where a variable should live, the Go compiler performs escape analysis:

If the variable is short-lived and stays inside the function, it goes on the stack.

If its lifetime extends beyond the function, or its address is referenced elsewhere, it “escapes” to the heap.

This optimization minimizes GC overhead by keeping as many allocations on the stack as possible.

🔹 Go’s Garbage Collector

Go’s GC is built on a concurrent tricolor mark-and-sweep algorithm.

Mark Phase

The GC starts from roots (global vars, stack references) and traverses the object graph, marking reachable objects as live.
✅ This runs concurrently with your program, minimizing stop-the-world pauses.

Sweep Phase

After marking, the GC scans the heap, identifying unmarked (unreachable) objects and reclaiming that memory for reuse.

🔹 Tricolor Abstraction

The “tricolor” model helps GC track object states efficiently:

⚪ White → Not yet visited, candidates for collection.

⚫ Black → Already visited and confirmed reachable.

⚪➡⚫ Gray → Discovered but not fully scanned yet.

This ensures no reachable object is mistakenly collected.

🔹 Concurrency and Write Barriers

Since marking runs concurrently with goroutines, Go uses write barriers.
Whenever a pointer is written, the barrier ensures new or modified references are tracked correctly. This keeps heap memory consistent even while your app is running.

🔹 GC Tuning in Go

Go allows fine-tuning GC behavior to balance memory usage and performance:

GOGC → Controls the percentage growth of heap before a GC cycle runs.

Higher values → fewer collections, higher memory use.

Lower values → more frequent collections, lower peak memory.

Go 1.19+ → Introduced GOMEMLIMIT and runtime/debug.SetMemoryLimit to set a soft memory cap, improving control in memory-constrained environments.

✅ Takeaway

Go’s memory management strikes a balance between developer productivity and runtime performance. By leveraging escape analysis, concurrent GC, and tuning options, you can build apps that scale smoothly without manually managing memory.


This content originally appeared on DEV Community and was authored by Seyed Ahmad