10. Slices
Arrays are a bit inflexible, so you don’t see them too often in Go code. Slices, though, are everywhere. They build on arrays to provide great power and convenience.
A slice is a segment of an array. Like arrays, slices are indexable and have a length. Unlike arrays, this length is allowed to change. Here’s an example of a slice:
var x []int
The only difference between this and an array is the missing length between the brackets. In this case x has been created with a length of 0.
If you want to create a slice you should use the built-in make function:
x := make([]int, 5)
This creates a slice that is associated with an underlying int array of length 5. Slices are always associated with some array, and although they can never be longer than the array, they can be smaller or equal.
The make function also allows a 3rd parameter:
x := make([]int, 5, 10)
10 represents the capacity of the underlying array which the slice points to. When the capacity argument is omitted, it defaults to the specified length.
The length and capacity of a slice can be inspected using the built-in len and cap functions.
len(x) == 5
cap(x) == 10
Another way to create slices is to use the [low : high] expression:
1 arr := [5]int{1,2,3,4,5}
2 x := arr[0:5]
low is the index of where to start the slice and high is the index where to end it (but not including the index itself). For example while arr[0:5] returns [1,2,3,4,5], arr[1:4] returns [2,3,4].
For convenience we are also allowed to omit low, high or even both low and high. arr[0:] is the same as arr[0:len(arr)], arr[:5] is the same as arr[0:5] and arr[:] is the same as arr[0:len(arr)].
10.1 Slice Functions
Go includes two built-in functions to assist with slices: append and copy. Here is an example of append:
Program: sl1.go
1 package main
2
3 import (
4 "fmt"
5 )
6
7 func main() {
8 slice1 := []int{10, 20, 30}
9 slice2 := append(slice1, 40, 50)
10 fmt.Println(slice1, slice2)
11 }
The output is:
[10 20 30] [10 20 30 40 50]
append creates a new slice by taking an existing slice (the first argument) and appending all the following arguments to it.
Here is an example of copy:
Program: sl2.go
1 package main
2
3 import (
4 "fmt"
5 )
6
7 func main() {
8 slice1 := []int{10, 20, 30}
9 slice2 := make([]int, 2)
10 copy(slice2, slice1)
11 fmt.Println(slice1, slice2)
12 }
The output is:
[10 20 30] [10 20]
After running this program slice1 has [10,20,30] and slice2 has [10,20]. The contents of slice1 are copied into slice2, but since slice2 has room for only two elements only the first two elements of slice1 are copied.
10.2 Slice internals
A slice is a descriptor of an array segment. It consists of a pointer to the array (ptr in image below), the length of the segment (len), and its capacity (cap - the maximum length of the segment).

Slice
Now s := make([]int, 5) can be represented as:

Slice
The length is the number of elements referred to by the slice. The capacity is the number of elements in the underlying array (beginning at the element referred to by the slice pointer).
As we slice s, observe the changes in the slice data structure and their relation to the underlying array:
s = s[2:4]

Slice
Slicing does not copy the slice’s data. It creates a new slice value that points to the original array. This makes slice operations as efficient as manipulating array indices. Therefore, modifying the elements (not the slice itself) of a re-slice modifies the elements of the original slice.
Program: sl3.go
1 package main
2
3 import "fmt"
4
5 func main() {
6 arr := [5]int{1, 2, 3, 4, 5}
7 slice := arr[0:5]
8 fmt.Println(slice)
9 fmt.Println("Len is: ", len(slice))
10 fmt.Println("Cap is: ", cap(slice))
11
12 slice = slice[2:4]
13 fmt.Println(slice)
14 fmt.Println("Len is: ", len(slice))
15 fmt.Println("Cap is: ", cap(slice))
16 }
The output is:
[1 2 3 4 5]
Len is: 5
Cap is: 5
[3 4]
Len is: 2
Cap is: 3
Slicing does not copy the slice’s data. It creates a new slice value that points to the original array. This makes slice operations as efficient as manipulating array indices.
Slices provide a dynamic window onto the underlying array.
10.3 Passing a slice to a function
If you have a function which must operate on an array, create a slice reference and pass that to the function.
For example, here is a function that sums all elements in an array:
Program: sl4.go
1 package main
2
3 import (
4 "fmt"
5 )
6
7 func sum(a []int) int {
8 s := 0
9 for i := 0; i < len(a); i++ {
10 s += a[i]
11 }
12 return s
13 }
14
15 func main() {
16 var arr = [5]int{0, 1, 2, 3, 4}
17 fmt.Println("Sum is: ", sum(arr[:]))
18 }
The output is:
Sum is: 10