What does the caller see after calling modify?
Question 484MediumGo 1.22 to 1.25
func modify(s []int) {
s[0] = 99
s = append(s, 4)
s[1] = 42
}
func main() {
x := []int{1, 2, 3} // len 3, cap 3
modify(x)
fmt.Println(x) // ?
y := make([]int, 3, 4) // len 3, cap 4
modify(y)
fmt.Println(y, y[:4]) // ?
}
Output: [99 2 3], then [99 42 0] [99 42 0 4].
A slice is passed as a header (pointer, len, cap) by value. s[0] = 99 writes through the shared pointer, so the caller sees it in both cases.
For x (cap 3), append must reallocate. s now points to a new array, so s[1] = 42 is not visible to the caller. For y (cap 4), append writes in place and s[1] = 42 reaches the shared array. The caller's header still has length 3, though, so the appended 4 is only visible by reslicing to y[:4].
Rule: a function that appends must return the new slice (s = f(s)), as append does, or take a *[]T.
More on Tricky Output & Code-Review Puzzles
- Q482What do f(), g(), and h() return?
- Q483What does this append puzzle print?
- Q485Code review: what is wrong with returning a small sub-slice of a large buffer, and what does s[low:high:max] fix?
- Q486Array vs slice in range: what prints?
- Q487Why doesn't this loop update the users?
- Q488Why is err != nil true here even though the function returned a nil pointer?