Reputation: 1063
In Go, why does this code work:
package main
import (
"fmt"
)
func main() {
a := []int{1}
a = a[1:]
fmt.Println(len(a))
}
but this doesn't:
package main
import (
"fmt"
)
func main() {
a := []int{1}
a = a[2:]
fmt.Println(len(a))
}
I've heard about capacity in slices, can someone elaborate it?
Upvotes: 2
Views: 28106
Reputation: 2265
Slice's capacity is always at least the same with slice's length. When unspecified, the default is always the same as length.
The definition of length of a slice is the number of element set into the slice.
The definition of capacity of a slice is the whole blocks of the slice can provide which is hidden from the caller and has default values of empty(0 for int, "" for string).
When you call value of a certain index like this a[x]
then it will get the value at index x
within range of lenght.
But when you re-slice the slice like this a[x:y]
then it will get the slice at index x
within range of capacity till y(max value must be the same with capacity). So as a caller of the slice, you can get the hidden elements of slice within the whole slice structure which default values are empty.
If you don't specify the end of re-sclicing(y) like you did above -> a[2:], then the default end of the re-slicing will be set to lenght, which make your call to a[2:]
imply to a[2:1]
since lenght of slice is 1. Think about it, calling a sub-slice of a[2:1]
, what would happen?. Exactly as the error message told us:
panic: runtime error: slice bounds out of range [2:1]
because you're calling sub-slice from the index which is not even within range of capacity(the whole structure of the slice it self). Even if 2 is within the range of slice's capacity, your call is overlapping because the starting index is larger than the capacity.
For summarize:
Upvotes: 2
Reputation: 489828
The Go specification contains the answer to both of your questions:
Slice expressions
Slice expressions construct a substring or slice from a string, array, pointer to array, or slice. There are two variants: a simple form that specifies a low and high bound, and a full form that also specifies a bound on the capacity.
Simple slice expressions
[snippage]
For arrays or strings, the indices are in range if
0 <= low <= high <= len(a)
, otherwise they are out of range.
Since len(a)
is 1
, the index 1 is in range, but the index 2 is out of range.
Full slice expressions
For an array, pointer to array, or slice
a
(but not a string), the primary expressiona[low : high : max]
constructs a slice of the same type, and with the same length and elements as the simple slice expression
a[low : high]
. Additionally, it controls the resulting slice's capacity by setting it tomax - low
. Only the first index may be omitted; it defaults to 0. ...
Read the entire spec. It can be a bit slow going, but it's not all that long. There's no need to memorize it all, but having gone through the whole thing once, you should be able to remember that you read that somewhere, and then go back and find what you are looking for.
Upvotes: 10