Slices, maps and strings · 3 MIN READ

len is what you have, cap is what you can grow into

Predict when append allocates and when it writes in place.

A slice is three words: a pointer to an array, a length and a capacity. append writes into the existing array while the capacity allows it, and allocates a new one when it does not.

That single rule explains most slice surprises: whether a write is seen by another slice depends on whether an append happened to reallocate.

SEE THE IDEA

A slice sees part of a backing array

  1. 01

    Visible elements

    go
    len(s)

    Indices from 0 up to len(s)-1

  2. 02

    Reserved storage

    go
    cap(s)

    The reslicing limit from this start

  3. 03

    Growth

    go
    s = append(s, v)

    May reuse or replace the backing array

Length is the current view; capacity is the room available behind that view.

In practice

Use make with a capacity estimate when building a result incrementally. An append returns the updated slice header, so retain that returned value. The growth policy is an implementation detail; correct code must not depend on a particular capacity after an allocation.

Watch out

Capacity does not permit indexing beyond length. Reslice first when exposing an existing part of the backing array.

Official reference ↗

Read and predict

go
package main

import "fmt"

func main() {
	s := make([]int, 0, 4)
	s = append(s, 1, 2)
	fmt.Println(len(s), cap(s))
	s = append(s, 3, 4, 5)
	fmt.Println(len(s), cap(s))
}

What are the two length and capacity pairs?

Try it yourself

Trace each value and write down your reasoning. Copy the source into GopherForge or your local Go environment to compile and check it. This web page does not execute your code or send it to a compiler service.

Progress stays in this browser. No account needed.