Go语言切片上下界疑问:为何s[3:5]未触发越界panic?
Go切片未触发索引越界的原因解析
代码与输出对比
示例代码
package main import "fmt" func main() { s := []int{2, 3, 5, 7, 11, 13} fmt.Println("check 1: ",s, len(s)) s = s[1:4] fmt.Println("check 2: ",s, len(s)) s = s[3:5] fmt.Println("check 3: ",s, len(s)) s = s[1:] fmt.Println("check 4: ",s, len(s)) }
实际执行输出
check 1: [2 3 5 7 11 13] 6 check 2: [3 5 7] 3 check 3: [11 13] 2 check 4: [13] 1
预期输出
check 1: [2 3 5 7 11 13] 6 check 2: [3 5 7] 3 panic: runtime error: slice bounds out of range [3:5]
问题核心
执行s = s[1:4]后,切片s的可见元素是[3,5,7],长度为3,但执行s = s[3:5]并未触发越界panic,反而返回了[11,13],这是为什么?
原因解释
Go的切片本质是底层数组的视图,它包含三个关键属性:
- 指向底层数组的指针
len:当前切片可见的元素个数cap:从指针指向的位置到底层数组末尾的元素总数
当执行s = s[1:4]时:
- 原切片的底层数组是
[2,3,5,7,11,13],len=6,cap=6 - 新切片的指针指向原数组索引1(元素3),
len=4-1=3,cap=6-1=5
也就是说,此时切片s虽然只能看到前3个元素,但底层数组从指针位置开始还有5个元素(3,5,7,11,13)。
Go对切片索引的规则是:切片的右边界(结束索引)允许达到当前切片的cap值,而非仅仅len值。只要右边界不超过cap,就不会触发越界panic。
所以执行s = s[3:5]时:
- 起始索引3对应原数组的
1+3=4位置(元素11) - 结束索引5对应原数组的
1+5=6位置(开区间,实际取到索引5) - 最终切片取到原数组索引4、5的元素
11,13,长度为5-3=2,完全在cap=5的范围内,因此不会报错。
如果将代码改为s = s[3:6],右边界6超过了当前切片的cap=5,才会触发slice bounds out of range的panic。
总结
- 切片的
len是可见元素数,cap是底层数组剩余可用元素数 - 切片索引的右边界可以扩展到
cap,而非局限于len - 只有当索引超出
cap(或起始索引超出len)时,才会触发越界panic
内容的提问来源于stack exchange,提问作者vj sreenivasan
相关产品推荐
相关产品推荐

