切片不会在长度上惊慌,但在获得索引值等于长度时会惊慌

I have a string, and when I want to get the value at i index it panics, but when I slice out of the same string keeping lower index value as length then it doesn't panic. Wanted to know how 1 and 2 differs?

func main() {
    str := "a"
    fmt.Println(str[1])  // 1 this panics
    fmt.Println(str[1:]) // 2 this doesn't
}

TLDR; In an index expression the index must be less than the length, and in a slice expression the length is a valid index.

In an index expression the index must be in range, else it panics. The index is in range if 0 <= i < length. Quoting from the spec:

In the index expression a[x]...

If a is not a map:

  • the index x is in range if 0 <= x < len(a), otherwise it is out of range

And:

For a of string type:

Your str string variable stores a string value which has a single byte: 'a'. Indexing starts at zero, so that single byte has index 0. Its length is 1, so there is no element at index 1.

In a slice expression:

a[low : high]

For arrays or strings, the indices are in range if 0 <= low <= high <= len(a), otherwise they are out of range.

In a slice expression the length is a valid index. So in your case indexing str like str[1:] will result in an empty string: "":

In a slice expression a[low : high]...

The result has indices starting at 0 and length equal to high - low.

A missing low index defaults to zero; a missing high index defaults to the length of the sliced operand.

So str[1:] is the same as str[1:len(str)] which is str[1:1]. The result string will have a length of high - low = 1 - 1 = 0: the empty string.