Now that you’ve seen all these ways to create slices, how do you choose which slice declaration style to use? The primary goal is to minimize the number of times the slice needs to grow. If it’s possible that the slice won’t need to grow at all, use a var declaration with no assigned value to create a nil slice, as shown in Example 2-2.
Example 2-2. Declaring a slice that might stay nil
var data []int
Note
You can create a slice using an empty slice literal:
var x = []int{}
This creates a slice with zero length and zero capacity. It is confusingly different from a nil slice. Because of implementation reasons, comparing a zero-length slice to nil returns false, while comparing a nil slice to nil returns true. For simplicity, favor nil slices.
If you have some starting values, or if a slice’s values aren’t going to change, then a slice literal is a good choice (see Example 2-3).
Example 2-3. Declaring a slice with default values
data := []int{2, 4, 6, 8} // numbers we appreciate
If you have a good idea of how large your slice needs to be, but don’t know what those values will be when you are writing the program, use make. The question then becomes whether you should specify a nonzero length in the call to make or specify a zero length and a nonzero capacity. There are three possibilities:
-
If you are using a slice as a buffer, then specify a nonzero length.
-
If you are sure you know the exact size you want, you can specify the length and index into the slice to set the values. This is often done when transforming values in one slice and storing them in a second. The downside to this approach is that if you have the size wrong, you’ll end up with either zero values at the end of the slice or a panic from trying to access elements that don’t exist.
-
In other situations, use make with a zero length and a specified capacity. This allows you to use
appendto add items to the slice. If the number of items turns out to be smaller, you won’t have an extraneous zero value at the end. If the number of items is larger, your code will not panic.
The Go community is split between the second and third approaches. I personally prefer using append with a slice initialized to a zero length. It might be slower in some situations, but it is less likely to introduce a bug.
Warning
appendalways increases the length of a slice! If you have specified a slice’s length using make, be sure that you mean toappendto it before you do so, or you might end up with a bunch of surprise zero values at the beginning of your slice.