go - 切片可以访问另一个超出范围的切片,但索引超出范围会导致恐慌
问题描述
我的代码:
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
我的问题:
为什么b[4:7]
即使索引 4 超出b
长度为 3 的范围也可以访问,但不能访问b[4]
?什么 Go 语言规则解释了这种行为?
解决方案
相关规则:Spec: Index 表达式和Spec: Slice 表达式。
简而言之:索引时,索引必须小于长度。切片时,上索引必须小于或等于容量。
索引时:a[x]
如果,
x
则索引在范围内0 <= x < len(a)
,否则超出范围
切片时:a[low: high]
对于数组或字符串,索引在范围内if
0 <= low <= high <= len(a)
,否则超出范围。对于切片,索引上限是切片容量cap(a)
而不是长度。
当你这样做时:
b := a[1:4]
b
将是一个与 共享后备数组的切片a
,其b
长度为3
,其容量为9
。因此,稍后切片b
甚至超出其长度也是完全有效的,直到其容量为9
. 但是在索引时,您始终可以仅索引切片长度所覆盖的部分。
我们使用索引来访问切片或数组的当前元素,如果我们想要创建数组或切片的片段,或者想要扩展它,我们会使用切片。扩展它意味着我们想要更大的部分(但仍然被支持数组覆盖)。
推荐阅读
- html - 根据多长时间前显示日期或日期名称的最近呼叫
- sockets - Dart 套接字不发送低于 31 的 utf-8 字符
- docker - 如何通过互联网连接到 Docker 容器中打开的 tcp 端口
- android - ExifInterface 无法处理来自 sdcard 的文件
- email - 未送达的邮件退回给发件人 Roundcube Plesk
- r - R中分类变量中跳跃的regsubsets包力
- php - 根据 WooCommerce 产品价格添加免费送货通知
- go - 最佳实践:将资产嵌入文件树?
- linux-kernel - SYN 洪水上的高 CPU 负载
- javascript - 如何为事件系列创建倒数计时器?