Slices and maps
Arrays versus slices, the backing-array trap, and how maps behave when a key is missing.
Slices
An array has a fixed length that is part of its type. A slice is a small header — pointer, length and capacity — describing a window over a backing array.
var grid [3][3]int // array: fixed size, copied on assignment
s := make([]int, 0, 4) // slice: len 0, cap 4
s = append(s, 10, 20, 30)
fmt.Println(len(s), cap(s)) // 3 4
head := s[:2] // shares the backing array
head[0] = 99 // so s[0] is now 99 too
safe := make([]int, len(s)) // copy when you need independence
copy(safe, s)
bounded := s[0:2:2] // three-index slice: appends cannot clobber s[2]| Operation | Cost and notes |
|---|---|
append(s, v) | Amortised O(1); may allocate a new array and copy |
s[i] | O(1) index access |
s[a:b] | O(1); shares memory with s |
copy(dst, src) | O(n) over min(len(dst), len(src)) |
append(s[:i], s[i+1:]...) | O(n) delete from the middle |
⚠️
A slice shares its backing array. Appending through a sub-slice can overwrite elements you thought were safe, and keeping a one-element sub-slice of a huge slice keeps the whole array alive in memory. Copy, or use the three-index form.
Maps
ages := map[string]int{"ada": 36, "grace": 45}
ages["alan"] = 41
v, ok := ages["missing"] // comma-ok: v is 0, ok is false
if !ok {
fmt.Println("no such key")
}
delete(ages, "alan")
for name, age := range ages { // iteration order is deliberately random
fmt.Println(name, age)
}
counts := map[string]int{}
counts["a"]++ // zero value makes this safe with no init- Reading a missing key returns the zero value, never an error. Use the comma-ok form whenever presence matters, because a stored zero and a missing key are different facts.
- A nil map can be read but writing to it panics. Always
makeit or use a literal before assigning. - Iteration order is randomised on purpose, so never depend on it. Sort the keys first when output must be stable.
- Maps are reference types: passing one to a function shares it. Guard concurrent access with
sync.Mutexor usesync.Map. maps.Keys,maps.Cloneandslices.Sortfrom the standard library replace a lot of hand-written loops.
FAQ
Slice or array?
Use slices almost always: they grow, they are cheap to pass, and they work with the standard library. Arrays are useful for fixed buffers and as map keys, since their length is part of the comparable type.
Why does my program panic with 'assignment to entry in nil map'?
You declared a map with
var m map[string]int and never allocated it. Reading from a nil map is fine, writing is not. Add m = make(map[string]int).Related
Go syntax, types and functions Goroutines and channels
Last refreshed 2026-09-18.