The capacity parameter in making a slice
in Go does not make much sense to me. For example,
aSlice := make([]int, 2, 2) //a new slice with length and cap both set to 2
aSlice = append(aSlice, 1, 2, 3, 4, 5) //append integers 1 through 5
fmt.Println("aSlice is: ", aSlice) //output [0, 0, 1, 2, 3, 4, 5]
If the slice allows inserting more elements than the capacity allows, why do we need to set it in the make() function?
The builtin
append()
function uses the specified slice to append elements to if it has a big enough capacity to accomodate the specified elements.But if the passed slice is not big enough, it allocates a new, big enough slice, copies the elements from the passed slice to the new slice and append the elements to that new slice. And returns this new slice. Quoting from the
append()
documentation:When making a slice with
make
if the length and capacity are the same, the capacity can be omitted, in which case it is defaulted to the specified length:Also note that
append()
appends elements after the last element of the slice. And the above slices already havelen(s) == 2
right after declaration so if you append even just 1 element to it, it will cause a reallocation as seen in this example:Output:
So in your example what you should do is something like this:
Output:
I recommend the following blog articles if you want to understand slices in more details:
Go Slices: usage and internals
Arrays, slices (and strings): The mechanics of 'append'
It is mainly an optimization, and it is not unique to go, similar structures in other languages have this as well.
When you append more than the capacity, the runtime needs to allocate more memory for the new elements. This is costly and can also cause memory fragmentation.
By specifying the capacity, the runtime allocates what is needed in advance, and avoids reallocations. However if you do not know the estimated capacity in advance or it changes, you do not have to set it, and the runtime reallocates what is needed and grows the capacity itself.