As mentioned before, an array's size is fixed. However, a slice is a dynamically-sized and flexible view into the elements of an array.
In practice, slices are much more common than arrays.
The type []T is a slice with elements of type T.
Declaration
A slice is formed by specifying two indices, a low and high bound, separated by a colon. This selects a half-open range which includes the first element, but excludes the last one.
a[low:high]a[1:4]// a slice includes 1 through 3 of `a`
A slice is just a section of an underlying array. It does not store any data. Changing the elements of one slice changes the corresponding elements of its corresponding array. So, other slices that share the same underlying array would see the changes.
Example
a reflects the modification b[0] = "XXX" because a and b share the same underlying array, whose second element is changed by this modification.
Slice Literals
A slice literal is like an array literal without the length. This is an array literal:
This is a slice literal:
This create the same array as above, and builds a slice that references it.
Example
Slice Defaults
We can use defaults instead of specifying the low or high bounds.
Consider an array var a[10]int. The following slide expressions are equivalent:
a[0:10]
a[:10]
a[0:]
a[:]
Example
Notice how the references to s changes when re-assign a slide to it every time.
Slice Length and Capacity
A slide has both a length and a capacity.
Length
Capacity
Definition
The number of elements the slice contains
The number of elements in the underlying array, counting from the first element in the slice
Usage
len(s)
cap(s)
A slice's length can be extended by re-slicing it, given that it has sufficient capacity.
Example
Zero Value
The zero value of a slice is nil. A nil slice has a length and capacity of 0 and has no underlying array.
Make a Slice
Remember we mentioned that arrays are fix-sized. Now, we can create dynamically-sized arrays using the built-in make function.
The make function allocates a zeroed array and returns a slice that refers to that array. The first argument is the array type; the second is the length; the third is the capacity.
Example
Slices of Slices
Since slices can contain any type, they can also contain other slices.
Example (Tic-Tac-Toe board: 2D array)
Append Function
The first parameter s of append is a slice of type T, and the rest are T values to append to the slice.
The resulting value of append is a slice containing all the elements of the original slice plus the provided values. If the backing array of s is too small to fit all the given values a bigger array will be allocated. The returned slice will point to the newly allocated array.
package main
import "fmt"
func main() {
s := []int{2, 3, 5, 7, 11, 13}
s = s[1:4]
fmt.Println(s)
s = s[:2]
fmt.Println(s)
s = s[1:]
fmt.Println(s)
}
[3 5 7]
[3 5]
[5]
package main
import "fmt"
func main() {
s := []int{2, 3, 5, 7, 11, 13}
printSlice(s)
// Slice the slice to give it zero length.
s = s[:0]
printSlice(s)
// Extend its length.
s = s[:4]
printSlice(s)
// Drop its first two values.
s = s[2:]
printSlice(s)
}
func printSlice(s []int) {
fmt.Printf("len=%d cap=%d %v\n", len(s), cap(s), s)
}
package main
import (
"fmt"
"strings"
)
func main() {
// Create a tic-tac-toe board.
board := [][]string{
[]string{"_", "_", "_"},
[]string{"_", "_", "_"},
[]string{"_", "_", "_"},
}
// The players take turns.
board[0][0] = "X"
board[2][2] = "O"
board[1][2] = "X"
board[1][0] = "O"
board[0][2] = "X"
for i := 0; i < len(board); i++ {
fmt.Printf("%s\n", strings.Join(board[i], " "))
}
}
X _ X
O _ X
_ _ O
package main
import "fmt"
func main() {
var s []int
printSlice(s)
// append on nil slices
s = append(s, 0)
printSlice(s)
// the slice grows as needed
s = append(s, 1)
printSlice(s)
// add more than 1 element at a time
s = append(s, 2, 3, 4, 5)
printSlice(s)
}
func printSlice(s []int) {
fmt.Printf("len=%d cap=%d %v\n", len(s), cap(s), s)
}