DMarlon Studio

Lesson 10 · 10 of 20

Slices · Go

Work with slices in Go, the lists that grow: append, len, cap, make and s[a:b] slicing that shares memory with the original.

Go · Slices in DMarlon Studio: the example's code and its output in the terminal

A slice is like an array without a fixed length: []string{...} is written with no number between the brackets. It is the most used list in Go, and len(playlist) tells you how many elements it has: 3.

append adds one or more elements at the end and returns the resulting slice, which you must store again: playlist = append(playlist, ...). If you do not assign it, the change is lost.

playlist[from:to] takes a slice of the slice: from position from up to the one before to. Leave out the first and it starts at 0 ([:2]); leave out the second and it runs to the end ([2:]). [1:4] gives elements 1, 2 and 3.

Under the hood, a slice uses an array with spare room: its capacity, cap. make([]int, 0, 4) creates an empty slice with room for 4. While there is room, append uses it; at the fifth element it no longer fits, so Go creates a bigger array (here of 8) and copies the data across.

A sub-slice is not a copy: it shares memory with the original. Changing firstTwo[0] also changes playlist[0], which becomes Overture. If you need an independent copy, use copy or append the elements to a new slice.

Code · main.go

package mainimport "fmt"func main() {	// A slice is a list that can grow: [] without a length.	playlist := []string{"Intro", "Sunrise", "Rain"}	fmt.Println(playlist, "len:", len(playlist))	// append returns the new slice: assign it back.	playlist = append(playlist, "Harbour", "Night Drive")	fmt.Println(playlist, "len:", len(playlist))	// s[from:to] goes from 'from' up to, not including, 'to'.	fmt.Println("First two:", playlist[:2])	fmt.Println("From the third:", playlist[2:])	fmt.Println("Middle:", playlist[1:4])	// make creates an empty slice with room (cap) for 4.	ratings := make([]int, 0, 4)	for i := 1; i <= 6; i++ {		ratings = append(ratings, i*10)		fmt.Printf("len=%d cap=%d %v\n", len(ratings), cap(ratings), ratings)	}	// A sub-slice shares memory with the original.	firstTwo := playlist[:2]	firstTwo[0] = "Overture"	fmt.Println("Changed through the sub-slice:", playlist[0])}

Output · go run main.go

[Intro Sunrise Rain] len: 3
[Intro Sunrise Rain Harbour Night Drive] len: 5
First two: [Intro Sunrise]
From the third: [Rain Harbour Night Drive]
Middle: [Sunrise Rain Harbour]
len=1 cap=4 [10]
len=2 cap=4 [10 20]
len=3 cap=4 [10 20 30]
len=4 cap=4 [10 20 30 40]
len=5 cap=8 [10 20 30 40 50]
len=6 cap=8 [10 20 30 40 50 60]
Changed through the sub-slice: Overture

Key points

  • []type{...} creates a slice; len gives its elements.
  • s = append(s, x): always keep what it returns.
  • s[a:b] goes from a to b-1; [:b] and [a:] are shortcuts.
  • make([]T, len, cap) sets aside room; cap shows it.
  • A sub-slice shares memory with its slice.

Exercise

Create a slice with the marks 7, 4, 9, 6 and add 8 with append. Print the middle three with slicing and then the sum of them all with a classic for.