make()
tally often knows roughly how many words a file holds before it starts. Growing a slice one reallocation at a time works, but telling Go the size up front is faster and clearer. make does that — as long as you remember that length and capacity are different promises.
The rule
make([]T, len, cap): len is filled with zeros, cap is room to grow.
a := make([]int, 3) // [0 0 0], len 3, cap 3
b := make([]int, 0, 1000) // [], len 0, cap 1000
c := make([]string, 2, 5) // ["" ""], len 2, cap 5- The length elements exist right away and hold zero values. You can index them:
a[2] = 7. - The capacity is extra room behind them.
appenduses it without reallocating until it is full. - Leave capacity out and it equals the length.
That gives two clean patterns:
// Pattern 1: unknown exact count, known rough size — append.
words := make([]string, 0, 1000)
for _, w := range incoming {
words = append(words, w)
}
// Pattern 2: exact count known — assign by index.
lengths := make([]int, len(words))
for i, w := range words {
lengths[i] = len(w)
}make also initialises maps — make(map[string]int) — and channels. It does not work for arrays or structs; those are ready as plain values. (You will also meet new(T), which returns a pointer to a zero T; it is not the tool for slices.)
A slice literal []string{} or a nil slice is fine when you have no size hint at all.
Why bother with a capacity hint? Each time append runs out of room it allocates a bigger array and copies everything across. For a thousand words that is a handful of wasted copies; for millions of rows it is real time. A good hint makes it a single allocation.
The shortcut
Decide by your loop: appending? → make(T, 0, n). Indexing? → make(T, n). Mixing the two is the bug.
The call
make([]string, 1000)— length 1000, so 1000 empty strings already exist.
Drills
Answer fast — trust the rule.
What does s := make([]int, 3); s = append(s, 5); fmt.Println(s) print?
What are len and cap of make([]byte, 2, 8)?
s := make([]int, 0, 5). What does s[0] = 1 do?
Which of these can make build?
Remember
make([]T, len, cap): len is filled with zeros, cap is room to grow.- Shortcut: appending →
make(T, 0, n); indexing →make(T, n). - Trap:
make(T, n)plus append leaves n zero values in front.
