Golang Memory Model Quiz
45 comprehensive questions on Golang's memory model, covering stack vs heap allocation, escape analysis, allocation patterns, garbage collection basics, and avoiding unnecessary allocations — with 25 code examples demonstrating memory management techniques.
Question 1
What is the stack in Go's memory model?
func f() {
x := 42 // Allocated on stack
y := "hello" // Allocated on stack
f2()
// x, y deallocated when f returns
}
func f2() {
z := make([]int, 10) // May escape to heap
}Question 2
What is the heap in Go's memory model?
func createSlice() []int {
return make([]int, 100) // Allocated on heap
}
func main() {
s := createSlice()
// s points to heap memory
_ = s
}Question 3
What is escape analysis in Go?
func noEscape() *int {
x := 42
return &x // x escapes to heap
}
func doesEscape() int {
x := 42
return x // x stays on stack
}Question 4
When does a variable escape to the heap?
func escapes() *int {
x := 42
return &x // Address returned, escapes
}
func doesntEscape(x *int) {
*x = 42 // Parameter already on heap
}
func conditionalEscape(b bool) *int {
if b {
x := 42
return &x // Escapes due to conditional return
}
return nil
}Question 5
How can you check if variables escape?
go build -gcflags='-m' main.goQuestion 6
What is garbage collection in Go?
func main() {
for {
s := make([]int, 1000) // Heap allocation
_ = s
// s becomes garbage when loop iterates
}
// GC will eventually free unreachable memory
}Question 7
What causes GC pressure?
func highPressure() {
for {
s := make([]byte, 1024*1024) // 1MB allocations
_ = s
// Creates lots of garbage quickly
}
}Question 8
How does Go's GC work?
Question 9
What is a GC pause?
Question 10
How can you reduce heap allocations?
func bad() []int {
return make([]int, 100) // Allocates new slice each call
}
func good() []int {
s := make([]int, 0, 100) // Pre-allocate capacity
return s[:0] // Reuse slice
}Question 11
What is object pooling in Go?
var pool = sync.Pool{
New: func() interface{} {
return make([]byte, 1024)
},
}
func process() {
buf := pool.Get().([]byte)
defer pool.Put(buf) // Return to pool
// Use buf
}Question 12
What is the difference between stack and heap allocation performance?
func stackAlloc() {
x := 42 // ~1ns allocation
_ = x
}
func heapAlloc() {
x := new(int) // ~10-50ns allocation + GC overhead
_ = x
}Question 13
What is memory fragmentation?
Question 14
How does Go's allocator work?
Question 15
What is a memory leak in Go?
func leak() {
ch := make(chan int, 1)
go func() {
for {
<-ch // Goroutine never exits
}
}()
// Forgot to close ch or signal goroutine to exit
}Question 16
How can you profile memory usage in Go?
import _ "net/http/pprof"
go func() {
log.Println(http.ListenAndServe("localhost:6060", nil))
}()
// Then: go tool pprof http://localhost:6060/debug/pprof/heapQuestion 17
What is the GOGC environment variable?
export GOGC=200 // GC at 200% heap growth (default 100)
./myprogramQuestion 18
What is a finalizer in Go?
type Resource struct {
handle unsafe.Pointer
}
func (r *Resource) Close() {
// Cleanup code
}
func init() {
runtime.SetFinalizer(r, (*Resource).Close)
}Question 19
How can you avoid string concatenation allocations?
func bad() string {
s := ""
for i := 0; i < 100; i++ {
s += strconv.Itoa(i) // Allocates new string each time
}
return s
}
func good() string {
var b strings.Builder
for i := 0; i < 100; i++ {
b.WriteString(strconv.Itoa(i))
}
return b.String() // Single allocation
}Question 20
What is interface{} allocation?
func box(x int) interface{} {
return x // Allocates box for int
}
func unbox(i interface{}) int {
return i.(int) // No allocation
}Question 21
How does slice growth affect memory usage?
s := make([]int, 0, 10)
for i := 0; i < 15; i++ {
s = append(s, i) // Grows capacity: 10 -> 20 -> 40...
}
// Wastes memory if final size is much smaller than capacityQuestion 22
What is the memory model for channels?
ch := make(chan int, 10)
go func() {
ch <- 42 // Value copied to heap if buffered
}()
x := <-ch // Value copied from heapQuestion 23
How can you optimize map allocations?
func bad() {
for i := 0; i < 1000; i++ {
m := make(map[string]int) // Allocates new map each iteration
m["key"] = i
process(m)
}
}
func good() {
m := make(map[string]int) // Allocate once
for i := 0; i < 1000; i++ {
m["key"] = i
process(m)
clear(m) // Go 1.21+ clears map efficiently
}
}Question 24
What is the cost of reflection?
func direct(x interface{}) {
s := x.(string) // Fast type assertion
}
func reflect(x interface{}) {
v := reflect.ValueOf(x) // Slow reflection
s := v.String()
}Question 25
How does GC handle circular references?
type A struct {
b *B
}
type B struct {
a *A
}
func main() {
a := &A{}
b := &B{}
a.b = b
b.a = a
// GC will collect both when they become unreachable
}Question 26
What is memory profiling in Go?
f, _ := os.Create("mem.prof")
defer f.Close()
runtime.GC() // Force GC
runtime.WriteHeapProfile(f)
// Analyze: go tool pprof mem.profQuestion 27
How can you reduce interface allocations?
func bad() {
var i interface{} = 42 // Boxed allocation
_ = i
}
func good() {
var x int = 42 // No boxing
_ = x
}
// Or use generics (Go 1.18+)
func generic[T any](x T) T {
return x // No boxing for concrete types
}Question 28
What is the impact of GC on latency?
Question 29
How can you implement memory-efficient linked lists?
type Node struct {
value int
next *Node
}
func bad() *Node {
return &Node{value: 1, next: &Node{value: 2}} // Multiple allocations
}
func good() *Node {
// Pre-allocate slice of nodes
nodes := make([]Node, 2)
nodes[0] = Node{value: 1, next: &nodes[1]}
nodes[1] = Node{value: 2}
return &nodes[0] // Single allocation
}Question 30
What is the memory cost of goroutines?
go func() {
// Each goroutine has its own stack
x := 42 // Stack allocation
_ = x
}()Question 31
How can you optimize struct allocations?
type BigStruct struct {
a, b, c, d int64
s string
}
func bad() {
return BigStruct{} // Returns by value, copies
}
func good() *BigStruct {
return &BigStruct{} // Returns pointer, no copy
}
func better() BigStruct {
var s BigStruct
// Modify s in place
return s // Single copy
}Question 32
What is the memory model for closures?
func createClosure(x int) func() int {
return func() int {
return x // x captured by closure
}
}
func main() {
f := createClosure(42)
// x is heap-allocated because closure escapes
}Question 33
How can you monitor GC performance?
import "runtime/debug"
debug.SetGCPercent(100) // Default
debug.SetGCPercent(-1) // Disable GC
debug.SetGCPercent(200) // Less frequent GCQuestion 34
What is the memory impact of defer?
func withDefer() {
defer cleanup() // Allocates closure if cleanup captures variables
}
func withoutDefer() {
cleanup() // Direct call, no allocation
}Question 35
How can you implement zero-allocation logging?
func bad() {
log.Printf("User %s logged in", user) // Allocates for formatting
}
func good() {
if log.Level >= log.Info {
log.Info("User logged in", "user", user) // Structured logging, no allocation if disabled
}
}Question 36
What is the memory model for maps?
m := make(map[string]int, 100) // Pre-allocates space
m["key"] = 42
// Map grows dynamically, potentially reallocatingQuestion 37
How can you reduce string allocations?
func bad(s string) string {
return strings.ToUpper(s) // Allocates new string
}
func good(s string) string {
// If possible, work with []byte
b := []byte(s)
for i := range b {
if 'a' <= b[i] && b[i] <= 'z' {
b[i] -= 32
}
}
return string(b) // Single allocation
}Question 38
What is the memory cost of panic/recover?
func mayPanic() {
defer func() {
if r := recover(); r != nil {
// Handle panic
}
}()
// Code that may panic
}Question 39
How can you optimize JSON marshaling memory usage?
func bad(v interface{}) {
data, _ := json.Marshal(v) // Allocates for marshaling
send(data)
}
func good(v interface{}) {
var buf bytes.Buffer
json.NewEncoder(&buf).Encode(v) // Streams to buffer
send(buf.Bytes())
}Question 40
What is the memory model for slices?
s := make([]int, 3, 10) // len=3, cap=10
s = append(s, 1) // Uses existing capacity
s = append(s, make([]int, 8)...) // May reallocate if exceeds capacityQuestion 41
How can you implement memory-efficient caching?
type Cache struct {
mu sync.RWMutex
items map[string]*Item
}
type Item struct {
value interface{}
expiry time.Time
}
func (c *Cache) cleanup() {
// Periodic cleanup of expired items
}Question 42
What is the impact of large object allocations?
func allocateLarge() {
data := make([]byte, 1024*1024) // 1MB allocation
// If this escapes, it's heap allocated
process(data)
}Question 43
How can you reduce function call overhead?
func inlineMe(x int) int {
return x * 2
}
func caller() {
result := inlineMe(5) // May be inlined by compiler
}Question 44
What is the memory model for interfaces?
var i interface{} = 42
// Interface value contains:
// - itab: type information and method table
// - data: pointer to concrete value (heap allocated)Question 45
What is the most important memory optimization principle?
