在Go语言中,切片操作可能会导致越界错误。

huangapple go评论79阅读模式
英文:

Slicing: Out of bounds error in Go

问题

上述代码中的切片表达式 c := b[1:] 导致了越界错误。这是因为切片表达式 b[1:] 表示从索引为 1 的位置开始,取到切片 b 的末尾。然而,在这种情况下,切片 b 的长度为 0,因此无法取到末尾元素,导致越界错误。要解决这个问题,你可以确保切片 b 的长度大于等于 1,或者使用合法的切片表达式来创建切片 c

英文:
package main

import "fmt"

func main() {
	a := make([]int, 5)
	printSlice("a", a)
	b := make([]int, 0, 5)
	printSlice("b", b)
	c := b[1:]
    printSlice("c", c)
}


func printSlice(s string, x []int) {
    fmt.Printf("%s len=%d cap=%d %v\n",
	    s, len(x), cap(x), x)
}

The above gives me an out of bounds error:

a len=5 cap=5 [0 0 0 0 0]
b len=0 cap=5 []
panic: runtime error: slice bounds out of range

goroutine 1 [running]:
main.main()
   /private/var/folders/q_/53gv6r4s0y5f50v9p26qhs3h00911v/T/compile117.go:10 +0x150

Why is the slicing expression to create the c slice results in an error?

答案1

得分: 22

简而言之:问题不在于下界,下界可以等于或大于len()(上界由切片的cap()决定)。问题在于上界:它必须大于或等于下界。由于您没有指定上界,默认为len()(而不是cap()!),其值为0。而1不小于或等于0

规范:切片表达式:

> 对于数组或字符串,如果0 <= low <= high <= len(a),则索引在范围内,否则索引超出范围。对于切片,上界索引是切片容量cap(a),而不是长度。

由于您正在对切片进行切片,如果满足以下条件,索引就在范围内:

0 <= low <= high <= cap(a)

因此,这行代码:

c := b[1:]

是无效的,因为:

> 缺少的低索引默认为零;缺少的高索引默认为切片操作数的长度

所以在您的情况下,low = 1high = 0(隐式),不满足:

0 <= low <= high <= cap(a)

因此,以下表达式是有效的示例:

c := b[1:1]        // c len=0 cap=4 []
c := b[1:2]        // c len=1 cap=4 [0]
c := b[1:cap(b)]   // c len=4 cap=4 [0 0 0 0]
英文:

In short: The problem is not with the lower bound which can be equal to or greater than len() (the upper limit is dictated by cap() in case of slices). The problem is with the higher bound: it must be greater than or equal to the lower bound. And since you didn't specify the higher bound, it defaults to len() (and not to cap()!) which is 0. And 1 is not less than or equal to 0.

Spec: Slice expressions:

> For arrays or strings, the indices are in range if 0 &lt;= low &lt;= high &lt;= len(a), otherwise they are out of range. For slices, the upper index bound is the slice capacity cap(a) rather than the length.

Since you are slicing a slice, indices are in range if:

0 &lt;= low &lt;= high &lt;= cap(a)

So this line:

c := b[1:]

Is invalid, because:

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

So in your case low = 1 and high = 0 (implicit), which does not satisfy:

0 &lt;= low &lt;= high &lt;= cap(a)

So for example the following expressions are valid:

c := b[1:1]        // c len=0 cap=4 []
c := b[1:2]        // c len=1 cap=4 [0]
c := b[1:cap(b)]   // c len=4 cap=4 [0 0 0 0]

huangapple
  • 本文由 发表于 2015年11月23日 03:15:53
  • 转载请务必保留本文链接:https://go.coder-hub.com/33859066.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定