Slices, maps and strings · 3 MIN READ

Two slices, one array

Spot the moment a subslice starts sharing writes with its parent.

Slicing does not copy elements. s[1:3] refers to the same backing array, so writes to overlapping elements are visible through both slices. An append that allocates a new array detaches the returned slice from that old storage.

A full slice expression such as s[1:3:3] limits capacity, forcing an append of another element to allocate. It does not detach the elements already in the view. Use copy or slices.Clone when the result must be independently mutable.

SEE THE IDEA

Slice headers can share one backing array

  1. 01

    Backing storage

    go
    [1, 2, 3, 4]

    The elements live here

  2. 02

    View A

    go
    a := data[:2]

    Has its own length and capacity

  3. 03

    View B

    go
    b := data[1:3]

    Overlapping elements refer to the same storage

Copying a slice copies its header, not its elements.

In practice

Decide whether a function returns a view or an independent copy. Use copy or slices.Clone when callers must not share mutations. A full slice expression can restrict capacity and force a later append to allocate, but it does not detach elements already visible in the slice.

Watch out

An append that fits capacity may overwrite values visible through another slice. An append that reallocates has different sharing behavior.

Official reference ↗

Work through the exercise

go
package main

// window returns the middle of s without letting the caller's
// appends overwrite the rest of s.
func window(s []int) []int {
	return s[1:3]
}

func main() {}
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.