Returning a pointer to avoid copying can make code slower. Go allocates a variable on the stack when it can prove the value will not be referenced after its function returns. Otherwise, the value escapes to the heap. section 12.5.1 section 12.5.2
Return a value or a pointer?
With inlining disabled, `sumValue` returns the sum as an `int`; `sumPtr` returns `&z`, so `z` must remain valid after the call. The pointer version therefore requires a heap allocation. A pointer is appropriate when the value needs to be shared, but it is not automatically a faster substitute for a copy. section 12.5.1
func main() {
a := 3
b := 2
c := sumPtr(a, b)
println(*c)
}
//go:noinline
func sumPtr(x, y int) *int { #1
z := x + y
return &z
}
Inspect the returned address: `z` cannot disappear with the function’s stack frame because the caller still uses it. section 12.5.1
Each goroutine has its own stack; goroutines share the heap. Stack allocation is quick and stack frames clean themselves up. Heap allocation takes more work and leaves cleanup to the garbage collector, so unnecessary heap allocations can affect data-intensive applications. section 12.5.1 section 12.9
BenchmarkSumValue-4 992800992 1.261 ns/op 0 B/op 0 allocs/op BenchmarkSumPtr-4 82829653 14.84 ns/op 8 B/op 1 allocs/op
The reported benchmark shows the value-returning function at 0 allocations per operation and the pointer-returning function at 1. These results use the examples with inlining disabled; measure your own code rather than treating the timings as a general rule. section 12.5.1
When allocations matter, choose a change that fits the code:
- Check whether an API unnecessarily makes a value escape. Passing a pointer into a function does not by itself require a heap allocation; the value may stay on the caller’s stack. section 12.5.2
- Use `strings.Builder` for suitable string concatenation, avoid unnecessary `[]byte`-to-string conversions, and preallocate slices or maps when their size is known. section 12.6
- Consider compiler optimizations and `sync.Pool` where appropriate, while keeping readability and semantics ahead of premature optimization. section 12.6 section 12.0
To test an assumption about an escape, inspect compiler output with `go build -gcflags "-m=2"`. Allocation reports from `testing.B.ReportAllocs` count heap allocations, not stack allocations. Diagnose the costly path before changing an API solely to reduce allocations. section 12.5.2 section 12.5.1










