This puzzle comes from go-traps.appspot.com: package main import "fmt" func main() { a := make([]int, 3, 4) a[0], a[1], a[2] = 0, 1, 2 b := append(a, 66) b[0] = 6 c := append(a, 77) c[0] = 7 d := append(a, 88, 99) d[0] = 9 fmt.Println(a) fmt.Println(b) fmt.Println(c) fmt.Println(d) } I think this is a good tutorial to explain the nitty-gritty behind the slice in Go , so I will analyze this issue detailedly. But before our journey, let’s get into some preliminaries of slice first: The internals of a slice is like the following diagram:

A slice consists of 3 components:

a) ptr: A pointer which points to the start position of slice in the underlying array;

b) len (also known as length, and its type is int ): the number of the valid elements of the slice;

b) cap (also known as capacity, and its type is int ): the total number of slots of the slice.

Now that we have known the construction of the slice, we can explain the problem step by step:

(1)

a := make([]int, 3, 4) a[0], a[1], a[2] = 0, 1, 2

The above statements are very general. Now the a slice is as follows:

(2)

b := append(a, 66)

Since the capacity of a is 4 , and the length of a is 3 , so a has a free slot for storing the new element: 66 . Besides this, the operation of “ append(a, 66) ” assigns to a new variable: b , so the value of a doesn’t change: len is still 3 ; cap is still 4 ; ptr still points the original array, but the content of original array is modified: the 4th element is 66 now. Because b is the assignee of “ append(a, 66) “, it points to the same underlying array of a , but The len of b is 4 :

After running “ b[0] = 6 “, now the memory layout is like this:

(3)

c := append(a, 77) c[0] = 7

Since the len of a is 3 up to this time, the program will consider there is an available slot. The result is the 4th element in the array will be changed to 77 from 66 . “ c[0] = 7 ” will modify the 1st element. Now the ptr s of a , b and c all point to the same array:

(4)

d := append(a, 88, 99) d[0] = 9

Since a only has 1 accessible slot, “ append(a, 88, 99) ” will relocating a new array (the size will be doubled to be be more efficient, that is from 4 to 8 in this case.). So now the ptr of d points to a new array, and the final result should be here:

To wrap out this discussion, I want to quote the following statement from go-traps.appspot.com:

A good rule of thumb for non-specialists would be “never call append without assigning back to the same variable”.