Reputation: 5172
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
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