Slices
Slices over Arrays
In Go, we seldom use raw arrays directly. Rather, Slices are more common.
Define Slices
1 | arr := [...]int{0, 1, 2, 3, 4, 5, 6, 7} |
In the code above, arr
is an array and s
is a slice. In Go, slices are half open. So s
is [2,3,4,5]
The output will be
1 | arr[2:6] = [2 3 4 5] |
Note if array is defined as below, it’s not an array, but a slice, ...
is required between []
1 | arr := []int {0,1,2,3} |
The slices can be flexible with boundaries:
1 | package main |
The outputs will be:
1 | arr[2:6] = [2 3 4 5] |
Slice is a View
A slice is not a value type, and it doesn’t hold any data. According to Go Doc, it’s a view of array.
1 | package main |
The outputs will be:
1 | Before updateSlice(s1) |
Since slice is a view of the array, when we change the value in slice, the corresponding value in array will be changed as well.
So we could refactor printArray
in Arrays post from Talkgolang.com
1 | func printSlice(arr []int) { |
The outputs will be:
1 | Index: 0 --- Value: 100 |
Note, when invoking printSlice
, we can only pass the argument as a slice arr[:]
not as an array arr
. printSlice(arr)
will report error.
Re-slicing
Slices can be based on another slice.
1 | arr := [...]int{0,1,2,3,4,5,6,7,8,9} |
The outputs will be
1 | s1: [0 1 2 3 4] |
Advanced Slicing
Let’s review some more complex concepts in slices.
Slicing “out of index”
See the example below:
1 | arr := [...]int{0,1,2,3,4,5,6,7} |
In the example above, s1
only has 4 elements, but s2
tries to slice “out of the index”. What’s s1
and s2
?
Here’s the output:
1 | s1: [2 3 4 5] |
It’s interesting that:
- slicing out of the
s1
index won’t report error - the last element
6
ins2
does not even exist ins1
If we attempt to get 6
in s1
and assume its index is 4
, by running fmt.Println(s1[4])
, we will get a runtime error
1 | panic: runtime error: index out of range [4] with length 4 |
When a slice is created, it contains the following information:
- pointer, the starting index of the slice
- length, the length of the slice
- capacity, the capacity of the original array
So the slice can be extended as long as its index does not exceed the capacity.
Another important feature of slice is, it can be extended forward but not backward. e.g. elements
0
and1
in the original array is not visible to s2 slice, ass1
pointer only starts at element2
.
We could get the length and capacity with built-in len
and cap
methods.
1 | fmt.Printf("s1 = %v, len(s1) = %d, cap(s1) = %d\n", s1, len(s1), cap(s1)) |
The output will be:
1 | arr = [0 1 2 3 4 5 6 7] |
So the capacity of s2
is 3, if it wants to access element beyond 7
in the original arr, it will report runtime error:
1 | panic: runtime error: slice bounds out of range [:7] with capacity 6 |