Why does append modify passed slice

Performance is the big reason. Creating a new slice and copying all the elements over to it is expensive, so the slice code doesn’t copy without good reason. However, if you exceed the slice’s capacity, it grows by a suitable amount by copying the underlying slice. That means that the slice that’s returned from append may not be the same slice you passed in.

The preferred way to use is:

args = append(args, newarg)

If you take a subslice, the capacity stays the same but your view into the slice changes. That means the missing elements are still there but outside the bounds of the new slice.

This explains the odd output of your code. You’re printing the result of append each time but not storing that result, which means args isn’t the same as what you printed.

The initial args slice is 3 elements big. For each index i – which is to say for 0, 1 and 2 – you take a subslice args[:i] and append all the elements of the remainder of the array args[i+1:] to it. That means that for:

i    args[:i]     args[i+1:]...   Result         args
0    {}           {"3", "8"}     {"3", "8"}     {"3", "8", "8"}
1    {"3"}        {"8"}          {"3", "8"}     {"3", "8", "8"}
2    {"3", "8"}   {}             {"3", "8"}     {"3", "8", "8"}

tl;dr you should always save the result of append, and if you want to make a copy so you can change it then make a copy yourself.

Leave a Comment