You’ve already seen two ways to declare a slice, using a slice literal or the nil zero value. While useful, neither way allows you to create an empty slice that already has a length or capacity specified. That’s the job of the built-in make function. It allows you to specify the type, length, and, optionally, the capacity. Let’s take a look:
x := make([]int, 5)
This creates an int slice with a length of 5 and a capacity of 5. Since it has a length of 5, x[0] through x[4] are valid elements, and they are all initialized to 0.
One common beginner mistake is to try to populate those initial elements using append:
x := make([]int, 5)
x = append(x, 10)
The 10 is placed at the end of the slice, after the zero values in elements 0–4 because append always increases the length of a slice. The value of x is now [0 0 0 0 0 10], with a length of 6 and a capacity of 10 (the capacity was doubled as soon as the sixth element was appended).
You can also specify an initial capacity with make:
x := make([]int, 5, 10)
This creates an int slice with a length of 5 and a capacity of 10.
You can also create a slice with zero length but a capacity that’s greater than zero:
x := make([]int, 0, 10)
In this case, you have a non-nil slice with a length of 0 but a capacity of 10. Since the length is 0, you can’t directly index into it, but you can append values to it:
x := make([]int, 0, 10)
x = append(x, 5,6,7,8)
The value of x is now [5 6 7 8], with a length of 4 and a capacity of 10.
Warning
Never specify a capacity that’s less than the length! It is a compile-time error to do so with a constant or numeric literal. If you use a variable to specify a capacity that’s smaller than the length, your program will panic at runtime.