Preallocating a slice can make growth intent explicit and avoid repeated capacity changes.

preallocation Use `make` with capacity when code already knows the likely number of appended values.

Slice Preallocation

expected
slice_preallocation.go
Replay: real traced execution (multi-file project)
package main

import "fmt"

func main() {
	var expected = 3
	values := make([]int, 0, expected)
	for i := 0; i < expected; i++ {
		values = append(values, i*i)
	}

	fmt.Println("expected=", expected)
	fmt.Println("length=", len(values))
	fmt.Println("capacity=", cap(values))
	fmt.Println("values=", values)
}
package main

import "fmt"

func main() {
	var expected = 1
	values := make([]int, 0, expected)
	for i := 0; i < expected; i++ {
		values = append(values, i*i)
	}

	fmt.Println("expected=", expected)
	fmt.Println("length=", len(values))
	fmt.Println("capacity=", cap(values))
	fmt.Println("values=", values)
}
package main

import "fmt"

func main() {
	var expected = 5
	values := make([]int, 0, expected)
	for i := 0; i < expected; i++ {
		values = append(values, i*i)
	}

	fmt.Println("expected=", expected)
	fmt.Println("length=", len(values))
	fmt.Println("capacity=", cap(values))
	fmt.Println("values=", values)
}
  1. expected ← 3, values ← []int{}

    5func main() {6  var expected→ 3 = 3 //@expected=1, 57  values→ []int{} := make([]int, 0, expected3)8  for i := 0; i < expected; i++ {
  2. values ← []int{0}

    pass 1 of 3
    7values := make([]int, 0, expected)8for i0 := 0; i < expected3; i++ {9  values→ []int{0} = append(values, i0*i)10}
    All 3 passes — pass 1 is the card above
    passivalues
    10[]int{} []int{0}
    21[]int{0} []int{0, 1}
    32[]int{0, 1} []int{0, 1, 4}
  3. fmt.Println("expected=", expected)

    12  fmt.Println("expected=", expected3)13  fmt.Println("length=", len(values[]int{0, 1, 4}))14  fmt.Println("capacity=", cap(values[]int{0, 1, 4}))15  fmt.Println("values=", values[]int{0, 1, 4})16}
    outputexpected= 3
    length= 3
    capacity= 3
    values= [0 1 4]
  1. expected ← 1, values ← []int{}

    5func main() {6  var expected→ 1 = 17  values→ []int{} := make([]int, 0, expected1)8  for i := 0; i < expected; i++ {
  2. values ← []int{0}

    7values := make([]int, 0, expected)8for i0 := 0; i < expected1; i++ {9  values→ []int{0} = append(values, i0*i)10}
  3. fmt.Println("expected=", expected)

    12  fmt.Println("expected=", expected1)13  fmt.Println("length=", len(values[]int{0}))14  fmt.Println("capacity=", cap(values[]int{0}))15  fmt.Println("values=", values[]int{0})16}
    outputexpected= 1
    length= 1
    capacity= 1
    values= [0]
  1. expected ← 5, values ← []int{}

    5func main() {6  var expected→ 5 = 57  values→ []int{} := make([]int, 0, expected5)8  for i := 0; i < expected; i++ {
  2. values ← []int{0}

    pass 1 of 5
    7values := make([]int, 0, expected)8for i0 := 0; i < expected5; i++ {9  values→ []int{0} = append(values, i0*i)10}
    All 5 passes — pass 1 is the card above
    passivalues
    10[]int{} []int{0}
    21[]int{0} []int{0, 1}
    32[]int{0, 1} []int{0, 1, 4}
    43[]int{0, 1, 4} []int{0, 1, 4, 9}
    54[]int{0, 1, 4, 9} []int{0, 1, 4, 9, 16}
  3. fmt.Println("expected=", expected)

    12  fmt.Println("expected=", expected5)13  fmt.Println("length=", len(values[]int{0, 1, 4, 9, 16}))14  fmt.Println("capacity=", cap(values[]int{0, 1, 4, 9, 16}))15  fmt.Println("values=", values[]int{0, 1, 4, 9, 16})16}
    outputexpected= 5
    length= 5
    capacity= 5
    values= [0 1 4 9 16]