Array — fixed-length, value-type container where the length is part of the type. Slice — a lightweight, dynamic view over a contiguous block of memory.
Arrays are assigned by value — the entire array is copied. This makes them safe to use without worrying about shared state but expensive for large sizes. Arrays are comparable and can be used as map keys.
1arr := [3]int{1, 2, 3}2copy := arr // full copy3copy[0] = 994fmt.Println(arr[0]) // 1 — original unchanged56// Arrays can be map keys7lookup := map[[32]byte]string{8 sha256.Sum256([]byte("hello")): "greeting",9}
Slices are three words in memory: a pointer, length, and capacity. When you slice an existing array or slice, the new slice shares the backing memory. This makes slicing efficient but means mutations can affect the original.
1original := []int{1, 2, 3}2sub := original[:2] // shares backing array3sub[0] = 1004fmt.Println(original[0]) // 100 — original changed!5original = append(original, 4) // may reallocate
When to use:
Common mistakes:
append — append(s, elem) returns a new slice header.== — only valid against nil; use slices.Equal otherwise.