Golang / Golang Internals and Memory Management Interview Questions
How do pointers work in Go and when should you pass by pointer vs by value?
Go is pass-by-value: every function argument is a copy. For types that are large or need to be mutated by the called function, passing a pointer avoids the copy and allows in-place modification. Understanding when to use pointers is essential for both correctness and performance.
// Pass by VALUE â mutation inside the function is invisible to caller func doubleValue(n int) { n *= 2 } // n is a copy x := 5 doubleValue(x) fmt.Println(x) // still 5 // Pass by POINTER â mutation is visible func doublePtr(n *int) { *n *= 2 } doublePtr(&x) fmt.Println(x) // 10 // Large structs â avoid copying by passing pointer type BigStruct struct { data [1024]byte } func processValue(b BigStruct) {} // copies 1 KB every call func processPtr(b *BigStruct) {} // copies only 8 bytes (pointer) // Value receiver vs pointer receiver on methods type Counter struct{ count int } func (c Counter) Get() int { return c.count } // value receiver â copy func (c *Counter) Inc() { c.count++ } // pointer receiver â mutates c := Counter{} c.Inc() // Go automatically takes &c fmt.Println(c.Get()) // 1 // Pointer vs nil â always check before dereferencing var p *int fmt.Println(p) // // fmt.Println(*p) // PANIC: nil pointer dereference
| Use pointer when... | Use value when... |
|---|---|
| The function must mutate the receiver/argument | The function is read-only |
| The type is large (>64 bytes typical threshold) | The type is small (int, bool, small struct) |
| The type has a sync.Mutex or similar non-copyable field | Immutability is desirable |
| Consistency: other methods use pointer receiver | Type is inherently value-like (time.Time, net/netip.Addr) |
More Related questions...