【问题标题】:Slice can access another slice out of range but indexing out of range causes panic切片可以访问另一个超出范围的切片,但索引超出范围会导致恐慌
【发布时间】:2020-12-01 08:14:30
【问题描述】:

我的代码:

package main

import (
    "fmt"
)

func main() {
    a := [10]int{0, 1, 2, 3, 4, 5, 6, 7, 8, 9}
    b := a[1:4]
    fmt.Println("a:", a)
    fmt.Println("b:", b)
    
    // Works fine even though c is indexing past the end of b.
    c := b[4:7]
    fmt.Println("c:", c)
    
    // This fails with panic: runtime error: index out of range [4] with length 3
    // d := b[4]
}

输出:

a: [0 1 2 3 4 5 6 7 8 9]
b: [1 2 3]
c: [5 6 7]

如果我取消注释包含d := b[4] 的行,则会导致此错误:

panic: runtime error: index out of range [4] with length 3

我的问题:

为什么即使索引 4 超出了长度为 3 的 b 的范围,但访问 b[4] 却不能访问 b[4:7],仍然可以访问?什么 Go 语言规则解释了这种行为?

【问题讨论】:

  • 为什么投反对票?我该怎么做才能使这个问题变得更好?
  • 为什么会出现“不可复制或由拼写错误”的原因的近距离投票?我的问题的哪一部分不可重现?

标签: go slice indexoutofboundsexception semantics


【解决方案1】:

相关规则:Spec: Index expressionsSpec: Slice expressions

简而言之:索引时,索引必须小于长度。切片时,上索引必须小于等于容量

索引时:a[x]

如果0 <= x < len(a),则索引x 在范围内,否则超出范围

切片时:a[low: high]

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

当你这样做时:

b := a[1:4]

b 将是与a 共享后备数组的切片,b 的长度将为3,其容量将为9。因此,稍后将b 切片甚至超出其长度也是完全有效的,直至其容量为9。但是在索引时,你总是可以只索引切片长度所覆盖的部分。

我们使用索引来访问切片或数组的当前元素,如果我们想要创建数组或切片的片段,或者想要扩展它,我们会使用切片。扩展它意味着我们想要更大的部分(但仍然被支持数组覆盖)。

【讨论】:

  • @lone-learner,必读:this 然后是this,您将 100% 了解切片。
  • icza, kostix:感谢您提供指向规范和 Go 博客的链接。我还在向A Tour of Go 学习 Go。成功完成游览后,我也会阅读您的链接。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-06-21
  • 2015-11-21
  • 1970-01-01
  • 2013-10-04
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多