What does this program print? (append inside a function with spare capacity)
Question 41HardGo 1.22 to 1.25
func add(s []int) {
s = append(s, 4)
s[0] = 100
}
func main() {
s := make([]int, 3, 4)
add(s)
fmt.Println(s, len(s), cap(s))
fmt.Println(s[:4])
t := []int{1, 2, 3} // len 3, cap 3
add(t)
fmt.Println(t)
}
Output:
[100 0 0] 3 4
[100 0 0 4]
[1 2 3]
In the first call cap is 4, so append writes 4 into the shared backing array at index 3 and makes no new allocation. s[0] = 100 also hits the shared array. The caller's header still says len 3, so it prints three elements. Reslicing to s[:4] (allowed up to cap) shows the hidden 4.
In the second call cap == len, so append allocates a new array, copies into it, and points the local s at it. s[0] = 100 then changes the new array, and the caller's t stays the same.
Key insight: whether a mutation "leaks" back to the caller depends on spare capacity at run time. That makes these bugs data-dependent and hard to reproduce.
More on Arrays, Slices, Maps & Strings
- Q40What is a slice header, and what really gets passed when you pass a slice to a function?
- Q42How does append grow a slice? Why is the resulting capacity sometimes not exactly double?
- Q43What does this print? (two appends on the same base slice)
- Q44What is the full slice expression a[low:high:max], and when would you use it?
- Q45What is the difference between a nil slice and an empty slice? When does it matter?
- Q46Explain the semantics of the built-in copy. Is it safe with overlapping slices?