> the problem is not with the language, it's with you
You're going too far there. The language already has action-at-a-distance behavior from references: they keep the array from being garbage collected. It would be both entirely possible and straightforwardly predictable to have them update to a new location, or enforce the rule you gave in your other post that there be no other users of the data when you're appending to it.
Only if you expected append to take linear time per usage, and literally just started using it without understanding what it does.
> enforce the rule you gave in your other post that there be no other users of the data when you're appending to it.
Another arbitrary hypothetical where you go using functions you don't understand, but for you to expect this you'd have to expect the language to punish reasonable uses of slices, like sharing the part you've already written and appending after that, and just having a local reference to one in a variable, with linear time behavior per usage. Which also makes it kind of unlikely that one ought to just assume the language works that way.
>for you to expect this
Oh, no, I wouldn't expect it to enforce a rule like that by default, but it would be a good thing to do when the behavior is so unpredictable.
>sharing the part you've already written and appending after that
You could require an immutable slice for that, in the situations where append is the most reasonable option.
Anyway I'm not trying to suggest this method. I'm just giving an example to support the idea that it could do something predictable.
What do you mean that the way append functions is obvious ? Because it doesn't seem obvious to me at all. Do you mean it's obvious to C/assembly programmers ? Obvious to someone who's implemented the Go standard library ?
This means slices work well, until the growth of one slice happens too fast and then, suddenly, your program crawls to a halt (and because it's doing more work, likely requests will pile up and make the offending slice grow even faster, resulting in effectively an infinite loop, and behaviour that is indistinguishable from the scheduler freezing, because now there is ridiculous growth in the number of goroutines).
The rule you gave in the other post is that in Go, everything behaves as a value. None of the complex Go datatypes do that. Slices, maps, interfaces, channels, ... all are half-half reference-value, with curious behaviour resulting from that. Go's simplicity comes from the fact that there are very few advanced datatypes to remember, and that the language makes it utterly impossible to implement any new ones in a reasonable way. So on the one hand you don't have idiots using B+trees where an array would have sufficed, but good luck expressing matrix equations in Go.
This results in O(n) complexity.
And this is assuming absense of memory pressure, if there is memory pressure it will very quickly becomes O(n^2) complexity, and god help you if it hits swap.
cap: 1
cap: 2
cap: 4
...
cap: 512
cap: 1024
cap: 1312
cap: 1696
cap: 2208
cap: 3072
cap: 4096
cap: 5120
cap: 7168
...
cap: 192797696
cap: 240997376
So it looks like it starts by doubling, then it gets weird between 1024 and 4096, and then it multiplies by 1.25.