Oh yes, I've had some quite hilarious (read: infuriating to debug) bugs because of that behaviour.
I imagine that's why almost everyone just use slices exclusively: you rarely if ever see "[SomeConstant]whatever { ... }" or even "[...]whatever { ... }" in Go codebases, it's almost always just "[]whatever { ... }": such literal slices have copy-on-append behaviour. And the syntax really nudges you into it which is nice.
> such literal slices have copy-on-append behaviour.
Only because literal slices default to cap == len (and a buffer of the same size). But if you create a sub-slice then all bets are off. That’s why some folks recommend always using a “full slice” if the result escapes:
A[x:y:y]
This way the cap() is set to the same value as the len(), and append will always trigger a copy. Essentially a cheaper (but riskier) version of a defensive copy.
I imagine that's why almost everyone just use slices exclusively: you rarely if ever see "[SomeConstant]whatever { ... }" or even "[...]whatever { ... }" in Go codebases, it's almost always just "[]whatever { ... }": such literal slices have copy-on-append behaviour. And the syntax really nudges you into it which is nice.