切片索引大于长度但小于容量会产生错误

Following code gives a error at runtime.

package main

import fmt "fmt"

func main(){

    type b []int
    var k = make([]b, 5, 10)
    fmt.Printf("%d
",k[8])
    fmt.Printf("%d", len(k))
}

Error is as follows.

panic: runtime error: index out of range

runtime.panic+0x9e /go/src/pkg/runtime/proc.c:1060
        runtime.panic(0x453b00, 0x300203f0)
runtime.panicstring+0x94 /go/src/pkg/runtime/runtime.c:116
        runtime.panicstring(0x4af6c6, 0xc)
runtime.panicindex+0x26 /go/src/pkg/runtime/runtime.c:73
        runtime.panicindex()
main.main+0x8d C:/GOEXCE~1/basics/DATATY~1/slice.go:9
        main.main()
runtime.mainstart+0xf 386/asm.s:93
        runtime.mainstart()
runtime.goexit /go/src/pkg/runtime/proc.c:178
        runtime.goexit()
----- goroutine created by -----
_rt0_386+0xbf 386/asm.s:80

While if k[0] or k[1] is printed, it runs fine. Can you please explain what exactly capacity means for slices.

Read the Go Programming Language Specification.

Length and capacity

The capacity of a slice is the number of elements for which there is space allocated in the underlying array. At any time the following relationship holds:

0 <= len(s) <= cap(s)

You are simply indexing, so the index must be less than the length. The relevant section of the Go specification says that

A primary expression of the form

a[x]

...

For a of type A or *A where A is an array type, or for a of type S where S is a slice type:

x must be an integer value and 0 <= x < len(a)

However, if you were "slicing" (e.g. a[6:9]), then it would work with indexes that are greater than the length but within the capacity.

var slice = make([]b, 5, 10)

is equal to

var array [10]b
slice := array[:5]

The difference is that when you use var slice = make([]b, 5, 10), you can't access the array under slice. The slice := array[:5] means the first element of slice is array[0] and the length of slice is 5, which means slice[0] == array[0], slice[1] == array[1], ... slice[4] == array[4]. Because you can only access the index that is less than the length(which means 0 <= index < length). The length of slice is 5 and the length of array is 10, so you can access array[8](0<=8<10) but can't access slice[8](8>5).

Full sample:

package main

import fmt "fmt"

func main(){

    type b []int
    var array [10]b
    slice := array[:5]
    // []
    fmt.Printf("%d
",slice[1])
    // []
    fmt.Printf("%d
",array[8])
    // panic: runtime error: index out of range
    fmt.Printf("%d
",slice[8])
}

Reference

  1. https://blog.golang.org/go-slices-usage-and-internals