In Python's Numpy library, `x[:]` also shares the same backing store. This bit me in the ass when I was learning Numpy.
Ouch. I guess this would be a reason to use strings more, since they're immutable.
Someone using a string when they really want a byte array/slice would fail review on its face. Excepting external APIs forcing "strings" on us, we only use the Go string type for UTF-8 code unit sequences (and this is a common assumption in the Go world).
Many Go libraries like to offer passing a byte slice to reuse as a destination. Many Go libraries take byte slices or structs containing them as arguments. A common result is "loop over some input, read it into the reusable slice, pass the slice to the next step". It even sort of works - until the next step does something asynchronous.
It doesn't help that:
- Lots of things return a new slice "sometimes" - _this_ append() result is safe to pass on; this other one is not; this other one "it depends".
- The `x[:]` idiom to turn an array into a slice looks exactly like a Python copy, but actually shares the same backing store.
In the end we basically banned reusing slices as a result. (The rule I tell new programmers is "if you pass the slice elsewhere in a loop, the slice needs to be allocated within the loop.") Which is a shame, because the performance gain from safe reuse is often significant. But until the type system blocks us from changes, usually in the oblivious callee, which turn a safe use into an unsafe one, it's simply too much effort to remember and review each case.