gotchagoMajor
Slice append and shared backing array gotcha
Viewed 0 times
slice appendbacking arrayshared slicesub-slice mutationfull slice expressioncopy slice
Problem
Slices derived from the same array share backing memory. Appending to a sub-slice within capacity mutates data visible to the original slice.
Solution
Copy a slice when you need an independent copy, or use the full-slice expression to limit capacity:
orig := []int{1, 2, 3, 4, 5}
// sub shares backing array with orig up to cap(sub)
sub := orig[:3]
sub = append(sub, 99) // overwrites orig[3]!
fmt.Println(orig) // [1 2 3 99 5] — surprise!
// FIX 1: explicit copy
copied := make([]int, 3)
copy(copied, orig[:3])
copied = append(copied, 99) // safe
// FIX 2: limit capacity with full slice expression
limited := orig[:3:3] // cap = 3, forces new allocation on append
limited = append(limited, 99) // safeWhy
A slice is a struct of (pointer, length, capacity). Two slices with the same pointer but different lengths share backing storage. append only allocates new memory when len exceeds cap.
Gotchas
- Functions that take a slice parameter and append to it may or may not affect the caller's slice depending on capacity
- Sorting a sub-slice sorts the underlying array, affecting all other slices sharing it
- json.Unmarshal into a slice field reuses existing backing array if capacity allows
Revisions (0)
No revisions yet.