misterbee
misterbee

Reputation: 5172

Why does Go slice `append()` not take a reference?

Go Lang's slice append() might allocate a new backing array to make room for the new item. Thus, after a call z = append(x,y), if z's front most elements are modified, x is essentially unspecified -- it might or might not have the same backing array as z, and z could mutate its backing array with z[0] = foo, which thus might or might not modify x's backing array.

So, why let this ugliness surface? Instead making it a program bug to assign the result of append to anything but its first argument, why not have append take a *[]T instead, so no reassignment is needed and no undefined variable is left dangling.

This wouldn't solve every case, because a = x; append(&x,y) would still make a undefined, but a partial improvement seems better than none.

Upvotes: 2

Views: 790

Answers (1)

joshlf
joshlf

Reputation: 23557

It's not quite true that in your first example (z = append(x, y)), x is undefined. Instead, x still points to the original contents of x, while z points to those contents and then some. As you mention, there are two possibilities:

  • cap(x) > len(x), in which case append simply returns x[:len(x)+1] (ie, extends the length of the returned slice to contain one extra element)
  • cap(x) == len(x), in which case append creates another array by copying over the contents of x and then appends y as the len(x)-th element.

In either of these cases, x is left largely unchanged in the sense that all of the elements of x are still there. You obviously have to be careful now that you potentially have two references to the same underlying data, but the point stands that keeping x around can be useful.

That said, I agree that maybe having append take a pointer might be simpler, and maybe this possible use case that I've just described isn't common enough to warrant the potentially confusing, mildly more verbose semantics.

Upvotes: 3

Related Questions