orange and lemon slices on a straw
Photo by Tangerine Newt on Unsplash

When Life Give You Lemons

A Go Brain Teaser

Miki Tebeka
3 min readSep 20, 2022

--

https://pragprog.com/newsletter/

What do you think the following program will print?

This program will print:

cart: [apple pear lemon] fruits: [apple pear lemon]

Appending to fruits affected cart as well. This result is due to how slices are built in Go.

If you look at slice.go you’ll see the following definition:

  • arrayis a pointer to the underlying array of data that the slice looks at
  • len is how many elements the slice it looking at
  • cap is the number of elements from array to the end of the underlying array

In our case, before we append to fruits the data looks like:

Both cart and fruits point to the same underlying array. When you append to fruits, Go will look to see if there’s more space in the underlying array; if there is — it’ll use that space. Otherwise, Go will allocate a new, bigger array. Copy over the data, and then append.

Here’s an example implementation of append for integers:

In our case, fruits has one more location in the underlying array. appendwill use the same underlying array that cart is looking at.

If you’ll print the lenand cap before the append:

You will see:

How can you fix this? You can use the full slice expression:

And now you’ll get:

cart: [apple pear milk] fruits: [apple pear lemon]

Now, when you print the len and cap before the append:

You will see:

Since fruits capacity is 2, Go will allocate and copy. Now the array field of cart and of fruits point to different arrays.

Slices can seem simple, but they have some very thorny edge cases that you need to be aware of. The good news is that in most cases — slices will behave just the way you think they will.

--

--