Slices, maps and strings · 3 MIN READ

A tiny slice can keep a large buffer alive

Recognize retained backing arrays and detach small long-lived results deliberately.

Visible length is not retained memory size. A small view can keep an entire allocation reachable. This is often noticed when a parser, cache or queue stores a few bytes from each large input and memory grows far beyond the stored lengths.

01

Follow the reference that survives

The function returns only sixteen bytes, but the result still points into the large allocation. As long as that backing array remains reachable, garbage collection cannot reclaim the array just because most of its bytes are outside the returned view.

go
func prefix() []byte {
    data := make([]byte, 8<<20)
    // A real program would read data here.
    return data[:16]
}
Read the code

The 8 MiB allocation is an illustrative size, not a threshold in Go. The problem is the lifetime mismatch: a short prefix outlives the large buffer it views.

02

Detach only what must outlive the input

Copy a small result when it needs an independent lifetime. The copy costs time and an allocation, so use it at a boundary such as inserting into a long-lived cache, not indiscriminately inside every short-lived operation.

go
func detachedPrefix(data []byte) []byte {
    n := min(16, len(data))
    return bytes.Clone(data[:n])
}
Read the code

Clipping capacity with data[:n:n] alone would not detach the original array. Setting one local variable to nil also does not help while another live view still refers to the allocation.

03

Measure retention rather than guessing

Distinguish bytes allocated over time from bytes still live. A temporary copy can increase allocation traffic while reducing retained memory. Inspect heap profiles in the real service, reproduce with representative payloads, and compare before and after. For slices of pointers, discarded elements can also retain pointed-to objects; use appropriate clearing or slices helpers when shrinking reusable storage.

TAKE THIS WITH YOU

Optimize lifetimes, not just lengths. A small copy can release a much larger backing array once all other references are gone.

Check your understanding

Which statement is correct about a long-lived subslice?

Go to the source

Progress stays in this browser. No account needed.