Thanks to Julia Evan’s latest post, I learned that creating new slices by sub-slicing an existing slice has an important caveat: They can sometimes use the same backing array! 😬
This is important to understand if you mutate the sub-slice.
Take the below example, wherein we accidentally mutate s1!
package main import ( "fmt" ) func main() { s1 := []int{0, 1, 2, 3, 4, 5} // len == 6, capacity == 6 s2 := s1[1:5] // len == 4, capacity == 5 // Modifies both s1 and s2, because they share the same backing array. s2[0] = 10 // Modifies both s1 and s2, because the length of s2 after adding the new // element does not exceed the capacity of the s2 slice. s2 = append(s2, 20) // Modifies only s2, because adding this element increases the length of s2 // beyond the capacity of the s2 slice. This allocats a new backing array, // copies all elements to it, and then appends 30 to it. So s1 does not get // modified. s2 = append(s2, 30) fmt.Println("s1", s1) fmt.Println("s2", s2) } Its output is:
...