A common mistake is treating a sliced range as an independent array. In Go, `s[low:high]` selects elements from `low` up to, but not including, `high`. The result has its own length and capacity but shares the original backing array. Changes to elements in the shared range are visible through both slices. section 3.4
An append changes an element you did not pass
Consider `s1 := []int{1, 2, 3}; s2 := s1[1:2]; s3 := append(s2, 10)`. The result is `s1=[1 2 10]`, `s2=[2]`, and `s3=[2 10]`. Although `s2` exposes only one element, it has capacity for another. `append` uses that space in the shared array, overwriting `s1[2]`. section 3.9
When passing a prefix to a function, choose the protection you need. `f(s[:2:2])` limits the new slice’s capacity to its length, so an append inside `f` cannot overwrite `s[2]` in the existing array. It does not isolate the first two elements: direct updates to them remain visible through `s`. Make a copy when the function must not change the original elements either. section 3.9
Figure 3.12 s[0:2] creates a two-length, three-capacity slice, whereas s[0:2:2] creates a two-length, two-capacity slice.
Compare the capacities of `s[0:2]` and `s[0:2:2]`: the third index controls whether a subsequent append has room in the original backing array. section 3.9
A short result can also retain much more memory than its length suggests. Returning `foos[:2]` from a slice of 1,000 structs leaves the backing array reachable. If the structs contain slices or other pointer fields, data held by the 998 inaccessible entries is not reclaimed in the demonstrated GC scenario. Copy the two wanted elements into a new slice, or clear the unwanted pointer fields before returning the prefix. section 3.10.2
The shared-array question matters in concurrent code too. Appending from separate goroutines to a shared slice with spare capacity can write the same backing-array location and cause a data race. Give each goroutine a copy when it needs an independently extendable slice. section 9.9















