【问题标题】:Why go doesn't report "slice bounds out of range" in this case? [duplicate]在这种情况下,为什么 go 不报告“切片边界超出范围”? [复制]
【发布时间】:2018-09-10 12:17:04
【问题描述】:

这是要重现的代码:

package main

import "fmt"

func main() {
    var v []int
    v = append(v,1)
    v = append(v,v[1:]...)
    fmt.Println("hi", v)

}

v[1] 会报告index out of range,但v[1:]... 不会,为什么?

【问题讨论】:

    标签: go slice


    【解决方案1】:

    这就是规范定义切片表达式的方式

    对于数组或字符串,如果 0

    https://golang.org/ref/spec#Slice_expressions

    这就是切片索引表达式的定义方式

    如果 0

    如果 x 在运行时超出范围,则会发生运行时恐慌

    https://golang.org/ref/spec#Index_expressions

    你的例子:

    v[1] 恐慌,因为根据上面的定义它是我们的范围(因为1 不符合0 <= x < len(a) 的要求)

    v[1:] 运行良好,因为它与v[1:len(v)] 相同并且符合if 0 <= low <= high <= cap(a) 的要求。

    【讨论】:

    • 这并不能解释为什么 v[1]v[1:]... 对于同一切片的行为不同
    • @user3698446 关于索引边界检查的运行时行为对于v[1:]v[1:]... 是相同的
    • 我的意思是 v[1]v[1:]...,这是一个错字,抱歉
    • 是的,我也添加了索引引用
    • 如果你能把你的回答说得更明确一点他们就不需要了,反正你的回答对我来说没问题,我会接受的:)
    【解决方案2】:

    v[1:] 返回一个列表类型。这里返回一个空列表,因为指定的切片范围内没有任何内容。因此不会引发错误。

    v[1] 正在尝试显式地越界访问元素。没有返回默认值,因此会引发错误。

    【讨论】:

      【解决方案3】:

      您可以在最后一个元素之后引用一个空切片,因为这在实现时很有用。

      例如。

       s := make([]byte, n)
       // Fill s with something...
       for len(s) > 0 { 
            b := s[0] // Get next byte
            s = s[1:] // Remove it from the slice
            // Deal with byte
       }
      

      ...如果 s[1:1] 不适用于 1 字节切片,则最后一次删除将无效。

      【讨论】:

        猜你喜欢
        • 2021-12-03
        • 1970-01-01
        • 2022-01-19
        • 1970-01-01
        • 2021-01-28
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多