Python lists and C++ vectors can make a Go slice look deceptively familiar. A
slice carries a reference to a backing array plus a length and capacity. Copying
the slice value copies that descriptor; it does not clone the elements. Two
descriptors can therefore expose overlapping storage. An array value, such as
[3]int, instead includes its elements, and its length is part of its type.
Changing an element through one overlapping slice is visible through the other. append returns a new descriptor and may reuse capacity or allocate another array. Always retain its returned slice. Do not depend on an implementation's capacity-growth formula, and do not use an observed allocation as an ownership guarantee. A function promising a snapshot must make its independence deliberate even when the input has ample spare capacity.
Choose the depth of a copy
For a slice of ints, make plus copy gives independent element storage. For a slice containing pointers, maps or slices, copying the elements still shares what those elements refer to. State the ownership policy at the depth your API actually needs. The build deliberately uses ints so its independence guarantee is precise and testable in both directions.
package main
import "fmt"
func main() {
xs := []int{3, 7}
alias := xs
snapshot := make([]int, len(xs))
copy(snapshot, xs)
alias[0] = 9
fmt.Println(xs, snapshot)
}The result is [9 7] [3 7]. A slice can be nil while its length is zero.
Appending to nil is valid. An allocated empty slice also has length zero but
need not be nil; later JSON serialization can distinguish these representations.
The contract may choose one explicitly.
Maps separate lookup from presentation
A missing map key returns the value type's zero value. For counts that makes
counts[word]++ convenient after initialization. Use the comma-ok lookup when
absence must be distinguished from a stored zero. A nil map supports reads but
cannot accept a new entry; initialize writable maps with make or a literal.
Assigning a map value shares its entries rather than copying them.
Map iteration has unspecified order. Tests and reports that require order must extract keys into a separate slice and sort it. Sorting that slice does not rearrange or mutate the map. Preserve keys whose count happens to be zero: a report of all keys is different from a report of positive counts.
The build combines an independent SnapshotAdd with fresh Frequencies maps and SortedKeys. Test spare-capacity input, mutation through both views and repeated calls. The two bugs distinguish accidental aliasing from lost multiplicity. Their failures come from observable contract violations, not timing or a particular hash-map traversal order.