Go

What does this append puzzle print?

Question 483HardGo 1.22 to 1.25
a := make([]int, 3, 10)
b := append(a, 1)
c := append(a, 2)
fmt.Println(a, b, c)
fmt.Println(len(a), len(b), cap(b))

Output:

[0 0 0] [0 0 0 2] [0 0 0 2]
3 4 10

a has spare capacity, so neither append allocates. Both write into index 3 of the same backing array. b and c are two headers (len 4) over one array, and the second append overwrote the first. a still has length 3, so it shows no change.

If a had been []int{0,0,0} (cap 3), each append would allocate a new array, and you would get [0 0 0 1] and [0 0 0 2]. Whether slices alias depends on capacity, which the calling code usually cannot see. That is why this bug is so hard to track down.

Fixes: always assign append back to the same variable (s = append(s, x)), or copy before you branch (b := append(slices.Clone(a), 1)), or cap the slice with a full slice expression, a[:len(a):len(a)], so the next append must reallocate.

More on Tricky Output & Code-Review Puzzles

All 38 Tricky Output & Code-Review Puzzles questions