Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Appending one element to nil slice increases capacity by two

Tags:

I have a nil slice:

var s1 []int // len(s1) == 0, cap(s1) == 0 

Which I append one element to:

s2 := append(s1, 1) // len(s2) == 1, cap(s2) == 2 

Why is appending one element to a nil slice increases the capacity by 2?

Printing the slices using fmt.Printf shows the following:

[] // s1 [1] // s2 

I am also confused about why re-slicing s2[0:2] shows a zero which was not in the original slice nor appended to it:

[1,0] // s2[0:2] 
like image 470
amiregelz Avatar asked Jul 23 '16 16:07

amiregelz


People also ask

Can you append to a nil slice?

Appending to nil slice: As we know that zero value slice type is nil and the capacity and the length of such type of slice is 0. But with the help of append function, it is possible to append values to nil slice.

Does append create a new slice?

The slice descriptor is composed of a pair of ints, one for len and one for cap, and a pointer to the underlying data. So, what append returns is indeed a new slice and what is passed to add option is indeed a copy of the slice descriptor.

Can you append a slice to a slice Golang?

When it comes to appending a slice to another slice, we need to use the variadic function signature dots. In variadic functions in Golang, we can pass a variable number of arguments to the function and all the numbers can be accessed with the help of the argument name.

What is capacity in slice?

The capacity of a slice is the number of elements in the underlying array, counting from the first element in the slice. The length and capacity of a slice s can be obtained using the expressions len(s) and cap(s) . You can extend a slice's length by re-slicing it, provided it has sufficient capacity.


1 Answers

Go is free to provide you more capacity than you request. This improves performance by reducing the number of allocations (and possibly copying) that are required. Capacity is just the amount of space reserved before another allocation would be required.

If you append 5 elements to this slice, at least in my experiments, the capacity is 8. This shouldn't be surprising, but also shouldn't be relied on. On different platforms, or different versions of the compiler, the actual result may be different, as long as the capacity is "sufficiently large" (equal to or greater than length).

The upper index bound of a slice is defined as its capacity:

For arrays or strings, the indices are in range if 0 <= low <= high <= len(a), otherwise they are out of range. For slices, the upper index bound is the slice capacity cap(a) rather than the length. A constant index must be non-negative and representable by a value of type int; for arrays or constant strings, constant indices must also be in range. If both indices are constant, they must satisfy low <= high. If the indices are out of range at run time, a run-time panic occurs.

This is why reading past the length is not causing a panic. Even so, you shouldn't think of those zeros as part of the slice. They are indexable by the slice, but fmt.Printf(s2) would correctly not show them because they are not part of the slice. Don't subscript this way.

In general, you want to be looking at length, not capacity. Capacity mostly is readable to assist in performance optimization.

like image 89
Rob Napier Avatar answered Sep 20 '22 09:09

Rob Napier