【问题标题】:Slicing: Out of bounds error in Go切片:Go 中的越界错误
【发布时间】:2016-02-24 20:27:24
【问题描述】:
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)
}

上面给了我一个超出范围的错误:

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

为什么创建c切片的切片表达式会出错?

【问题讨论】:

    标签: go slice


    【解决方案1】:

    前言:这个问题很好,反对票的来源是因为乍一看这个问题确实看起来像提问者根本不知道切片时的有效边界是什么。但这种情况并不常见!很少有人以甚至下限超出切片长度的方式切片切片!


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

    Spec: Slice expressions:

    对于数组或字符串,如果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]
    

    【讨论】:

    • 问题变得更加棘手,因为如果您使用非文字表达式(请参阅go.dev/play/p/Yv5EX1QNRD-),那么编译器将不会给出关于较低 > 较高的警告。在运行时,这种对切片的不合规性会转化为恐慌。表达式b[1:] 隐含地使用非文字表达式(len(b) 作为 icza 高亮显示)作为上限,最终导致恐慌。只是添加。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-09-11
    • 2016-09-26
    • 1970-01-01
    • 2016-04-12
    • 2017-09-23
    • 1970-01-01
    • 2011-12-21
    相关资源
    最近更新 更多