Slices in Go
Slices are dynamic views over arrays with length and capacity. They are idiomatic for collections.
Create
Create nil, literal, or allocated slices. make lets you specify length and optional capacity.
var a []int // nil slice (len=0, cap=0)
b := []int{1,2,3} // literal
c := make([]int, 3) // len=3, zeroed
d := make([]int, 0, 8) // len=0, cap=8
_ = a; _ = b; _ = c; _ = d
Append
append adds elements, growing capacity when needed. When reallocated, a new backing array is created.
s := []int{}
s = append(s, 1)
s = append(s, 2, 3)
s = append(s, []int{4,5}...) // spread
Copy
copy(dst, src) copies up to min(len(dst), len(src)) elements from src into dst.
src := []int{1,2,3}
dst := make([]int, len(src))
copy(dst, src) // copies min(len(dst), len(src))
Slicing
Slicing is half-open: a[i:j] includes i up to j-1. Defaults: a[:j] is from 0, a[i:] to end, a[:] copies header.
xs := []int{0,1,2,3,4,5}
sub := xs[1:4] // [1,2,3]
head := xs[:3] // [0,1,2]
tail := xs[3:] // [3,4,5]
Capacity growth
appendmay grow capacity (usually approx doubling)- Reallocation returns a new backing array; previous slices are unaffected
s := make([]int, 0, 1)
s = append(s, 1)
old := s
s = append(s, 2) // may reallocate
_ = old // old may still reference the old array
Zero value and nil
var z []int
fmt.Println(z == nil, len(z), cap(z)) // true, 0, 0
z = append(z, 1) // ok
Remove element (pattern)
// remove index i (preserve order)
s = append(s[:i], s[i+1:]...)
// remove without preserving order
s[i] = s[len(s)-1]
s = s[:len(s)-1]
Preallocate
n := 1000
xs = make([]int, 0, n)
for i := 0; i < n; i++ { xs = append(xs, i) }
Pitfalls
- Slices share backing arrays; copying a slice copies the header, not data
- Sub-slices keep the original array alive; use
copyto detach if needed - Iterating and mutating: range over indices when changing elements
- Taking addresses of range values points to the loop variable; index into the slice to take element addresses
Summary
- Use slices for dynamic collections
- Mind shared backing arrays and capacity growth
- Preallocate when size is known for performance