This question already has an answer here:
package main
import "fmt"
type Point struct {
X int
Y int
}
type Points struct {
P []Point
}
func main() {
data := Points{}
for i := 0; i < 10; i++ {
data.P = append(data.P, Point{
X: i,
Y: i*2,
})
}
fmt.Printf("%+v
", data.P[5:11]);
}
While the above program is run, it printed out:
[{X:5 Y:10} {X:6 Y:12} {X:7 Y:14} {X:8 Y:16} {X:9 Y:18} {X:0 Y:0}]
Why there are {X:0, Y:0} which seems to be automatically generated as the slice's length is 10 but I try to get 5:11?
I found the problem in my code and test with "raw" slice such as:
package main
import "fmt"
func main() {
v := []int{0,1,2,3,4,5,6,7,8,9}
fmt.Printf("%v
", v[5:11])
}
This simple program generates errors (as expected):
panic: runtime error: slice bounds out of range
goroutine 1 [running]:
panic(0x47a8e0, 0xc42000a130)
/usr/local/go/src/runtime/panic.go:500 +0x1a1
main.main()
/home/fxr/go/src/cmhwc/test2.go:7 +0x53
exit status 2
Why the first program does not panic?
</div>
Because when you use append() to add elements to a slice which has no more room for adding the new elements it creates a new one doubling its capacity copying the old elements as well as the new you're asking to add and returning a reference to that. Further down when you use slice syntax to ask for elements past the apparent end of the slice the length is actually applied to the underlying array created & returned by append.
As @JimB suggested in the comments, you can add a statement to print the capacity at every step in the append loop to see this happening:
fmt.Println(cap(data.P))
Should generate something like:
2
2
4
4
8
8
8
8
16
16