8 ms·
Wow I forgot how unergonomic go can be. And that example even is a potential memory leak...
by LukaD 5y ago
Wow I forgot how unergonomic go can be. And that example even is a potential memory leak...
- masklinn 5y ago> And that example even is a potential memory leak… Yup more generally a slice is not an actual vector, the backing array lives independently from the slice, meaning if you "reset" a slice a = a[:0] all the elements are still part of the backing array, and thus still referenced. That's also why write-sharing (which is trivial in Go) is super dangerous e.g. a := GetSlice() b := a[:] a = append(a, 1) b = append(b, 2) depending on the size of the backing array associated with slice `GetSlice` returns (aka the cap() of the slice), the last element of `a` might be 1 or 2.
- majewsky 5y agoUm, what? My impression was always that the last line would copy the underlying slice since someone has already appended to the original backing array. That's the whole point of why append is not in-place. You get a new slice value back because the extension may have happened by copying data into a new backing array.
- masklinn 5y ago> My impression was always that the last line would copy the underlying slice since someone has already appended to the original backing array. Nope. append only copies if there’s no room in the backing array, if there is it will just extend the slice in-place and set the new elements. So if there’s room, a will be extended in-place, with the new element set, then b will be extended in-place, overwriting the element set by a. Hell, how would append even know that somebody else appended to the backing array? As far is it can see that might as well be leftover garbage. > You get a new slice value back because the extension may have happened by copying data into a new backing array. That only happens if the backing array is full aka len() + new > cap().
- majewsky 5y ago> how would append even know that somebody else appended to the backing array? As far is it can see that might as well be leftover garbage. Well, the backing array knows its length and capacity, and the slice knows its length, so it's quite trivial to see that there are elements in the array beyond the length of the slice. EDIT: I'm shocked and appalled by the fact that you're completely right. https://play.golang.org/p/UZSlBMUlc_E https://play.golang.org/p/UZSlBMUlc_E
- masklinn 5y ago> Well, the backing array knows its length and capacity arrays don’t have capacity. The capacity of a slice is the length of its backing array (minus the offset of the slice in the array, which is why slices do need to store a cap separately). > it's quite trivial to see that there are elements in the array beyond the length of the slice. There are always elements in the array beyond the length of the slice (unless the slice is « at capacity »). > EDIT: I'm shocked and appalled by the fact that you're completely right. https://play.golang.org/p/UZSlBMUlc_E https://play.golang.org/p/UZSlBMUlc_E Yup. Go slices are fun. And by fun I mean error-prone. Well most of the trouble really comes from them having double-duty as actual slices and add-hoc pseudo vectors.