4 ms·
How do Go programmers deal with the fact that it is hard to reason about whether slices alias? Go lacks const, so there's no way to prevent your caller from mo
by millstone 9y ago
How do Go programmers deal with the fact that it is hard to reason about whether slices alias?
Go lacks const, so there's no way to prevent your caller from modifying the slice you return, or the callee from modifying the slice you pass it. Also the result of append() may or may not alias its parameter, depending on the allocator's mood that day.
Do Go APIs just defensively copy, or pepper APIs with "do not modify" warnings, or rely on runtime tests? Given the fact that append() may mask aliasing bugs, is there a way to make append() alias maximally?
- oconnor663 9y agoI make defensive copies when I'm worried about it. Append will reuse the current backing array when it has enough capacity to hold whatever you're appending. So to alias maximally like you suggested, you could try creating all your arrays/slices with lots of extra capacity. That would be pretty expensive, but you could try doing it one-off just to see what happens in your test suite?
- JelteF 9y agoIt definitely can lead to hard to find bugs. I even made an issue out of one case where it could happen in very unexpected ways (which is now fixed on the go master branch): https://github.com/golang/go/issues/21149 https://github.com/golang/go/issues/21149 Apart from the issue above I've found that it's usually quite easy to reason about though. Usually when you take a slice you either use it temporarily without modifying or you throw away the original one. In the rare case where you do still need both slices to outlive the same function you just copy one of them manually defensively.
- ominous_prime 9y agoIt's rarely a concern in practice. Public APIs should document if a slice may or may not be modified, for example: `io.Writer` says ` Write must not modify the slice data, even temporarily`, and `bufio.Scanner.Bytes()` says `The underlying array may point to data that will be overwritten by a subsequent call to Scan`. The `append` builtin may allocate a new array and copy, or reuse the same array, but the result should almost always be assigned back to the original variable. The only time you wouldn't assign it back to the same variable is when you are carefully managing the slices yourself for some specific reason, which should never be exposed via an API.
- catnaroek 9y agoDo you also rely on function documentation telling you whether it modifies its arguments, “even temporarily”? Or do you just read the source for every function you use, transitively?