Most of the time, when you want a data structure that holds a sequence of values, a slice is what you should use. What makes slices so useful is that you can grow slices as needed. This is because the length of a slice is not part of its type. This removes the biggest limitations of arrays and allows you to write a single function that processes slices of any size. After going over the basics of using slices in Go, I’ll cover the best ways to use them.
Working with slices looks a lot like working with arrays, but subtle differences exist. The first thing to notice is that you don’t specify the size of the slice when you declare it:
var x = []int{10, 20, 30}
Tip
Using [...] makes an array. Using [] makes a slice.
This creates a slice of type []int with an element type of int. The slice is initialized to hold three ints using a slice literal. Just as with arrays, you can also specify only the indices with nonzero values in the slice literal:
var x = []int{1, 5: 4, 6, 10: 100, 15}
This creates a slice of 12 ints with the following values: [1, 0, 0, 0, 0, 4, 6, 0, 0, 0, 100, 15].
You can simulate multidimensional slices and make a slice of slices:
var x [][]int
You read and write slices using bracket syntax, and, just as with arrays, you can’t read or write past the end or use a negative index:
x[0] = 10
fmt.Println(x[2])
So far, slices have seemed identical to arrays. You start to see the differences between arrays and slices when you look at declaring slices without using a literal:
var x []int
This creates a slice of ints. Since no value is assigned, x is assigned the zero value for a slice, which is something you haven’t seen before: nil. I’ll talk more about nil in the related discussion, but it is slightly different from the null that’s found in other languages. In Go, nil is an identifier that represents the lack of a value for some types. Like the untyped numeric constants you saw in this topic, nil has no type, so it can be assigned or compared against values of different types. A nil slice contains nothing.
A slice is the first type you’ve seen that isn’t comparable. It is a compile-time error to use == to see if two slices are identical or != to see if they are different. The only thing you can compare a slice with using == is nil:
fmt.Println(x == nil) // prints true