Slices in Go

Make a slice

A slice is a flexible view over a backing array: it can grow, and it passes around cheaply because only a small header is copied. Build one with a literal, or with make when you know the starting length.

package main import "fmt" func main() { nums := []int{1, 2, 3} fmt.Println(nums) names := make([]string, 2) names[0] = "Ada" fmt.Println(names) }

go run main.go

[1 2 3]
[Ada ]

Notice the missing length in []int: that empty bracket pair is exactly what tells Go you want a slice and not an array. Make with two arguments sets length and capacity together; the optional third argument reserves extra room for growth without reallocation.

Append grows it

Append returns a slice with new elements added at the end, and you must store the result back because growth can move the data to a larger array. Appending is the everyday way slices grow.

package main import "fmt" func main() { nums := []int{1, 2} nums = append(nums, 3, 4) fmt.Println(nums) }

[1 2 3 4]

Forgetting the assignment back is the classic beginner bug: the append happens, but the old variable still points at the short slice. Always write nums equals append of nums to keep the grown result.

Len vs cap

Len reports how many elements the slice holds right now, while cap reports how many fit before the next growth step must allocate. Watching both explains why some appends feel free and others copy.

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

2 5
5 5

Capacity is a performance detail, not a limit: append past it and Go allocates a bigger array automatically. Pre sizing with make avoids repeated copying when the final size is known in advance.

Slicing a slice

Cut a new slice out of an old one with low:high bounds, where low is included and high is excluded. The result shares the same backing array, so it starts as a window rather than a copy.

package main import "fmt" func main() { nums := []int{1, 2, 3, 4, 5} mid := nums[1:4] mid[0] = 9 fmt.Println(nums) }

[1 9 3 4 5]

Sharing cuts allocations but also surprises: writing through one slice shows up in the other. Copy with the builtin copy function when the new slice must live its own life.

Next: Maps

Article author: Arthur Isaev

Banner image