The curious case of Golang array and slices

We know that slices hold references to the underlying array, lets see a small code snippet which demonstrates it.

http://play.golang.org/p/hGLjK7Ukdu

Here is the output,

array = [1 2 3 4] , slice = [1 2 3]
array = [1 2 4 4] , slice = [1 2 4]

You can clearly see the value in the underlying array has changed

let’s append more element into the slice and see what happens,

http://play.golang.org/p/EV2FkbLBl-

Here’s the output

array = [1 2 3 4] , slice = [1 2 3]
array = [1 2 4 4] , slice = [1 2 4]
array = [1 2 4 5] , slice = [1 2 4 5]

In the last row of the output you could see that the value in the underlying has changed after appending an element into the array.

But here’s the challenge, since now the underlying array the slice is referring to is full (the underlying array is of size 4), lets see what happens to the underlying array on adding fifth element into the end of the slice.

http://play.golang.org/p/chr_P6VZdQ

Here is the output,

array = [1 2 3 4] , slice = [1 2 3]
array = [1 2 4 4] , slice = [1 2 4]
array = [1 2 4 5] , slice = [1 2 4 5]
array = [1 2 4 5] , slice = [1 2 4 5 6]

You could clearly see that the elements in the underlying array hasn’t changed ( check the last row of the output), this is because now the slice has grown beyond the size of the underlying array. But let’s see what would happen if we now alter an element of the slice within the bound of array.

http://play.golang.org/p/Nb8lmOuuDM

here is the output,

array = [1 2 3 4] , slice = [1 2 3]
array = [1 2 4 4] , slice = [1 2 4]
array = [1 2 4 5] , slice = [1 2 4 5]
array = [1 2 4 5] , slice = [1 2 4 5 6]
array = [1 2 4 5] , slice = [9 2 4 5 6]

If you see in the last row of the output the first element of the array didn’t change even though first element of the slice changed. This is because the slice after getting past the size of the underlying array it now creates a new copy of the array and points to this new array.