This question already has an answer here:
Here's the code to reproduce:
package main
import "fmt"
func main() {
var v []int
v = append(v,1)
v = append(v,v[1:]...)
fmt.Println("hi", v)
}
v[1]
will report index out of range
, but v[1:]...
won't, why?
</div>
That's how spec defines slice expressions
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.
https://golang.org/ref/spec#Slice_expressions
And that's how index expressions for slices are defined
the index x is in range if 0 <= x < len(a), otherwise it is out of range
if x is out of range at run time, a run-time panic occurs
https://golang.org/ref/spec#Index_expressions
For your example:
v[1]
panics because it's our of range as per the definition above (because 1
does not qualify the 0 <= x < len(a)
reqirement)
v[1:]
runs fine because it's identical to v[1:len(v)]
and fits the if 0 <= low <= high <= cap(a)
requirement.
v[1:] returns a list type. Here an empty list is returned as nothing comes in the slice range specified. Hence no error is thrown.
v[1] is trying to access element explicitly out of bound. No default value is returned hence an error is thrown.
You are allowed to reference an empty slice just past the last element, because this can be useful when implementing things.
Eg.
s := make([]byte, n)
// Fill s with something...
for len(s) > 0 {
b := s[0] // Get next byte
s = s[1:] // Remove it from the slice
// Deal with byte
}
...the last removal wouldn't be valid if s[1:1] didn't work on a 1 byte slice.