为什么切片的左边可以是数组的长度,按照道理来说应该越界了呀?
package main
import "fmt"
func main() {
var s = "whaomi"
var bs = []byte(s)
fmt.Println(bs[len(s):])
// error
// fmt.Println(bs[len(s)+1:])
}
数组长度是 6 ,按照 0 下标开始最后一位应该是 5 ,但是却可以使用切片从 6 开始 bs[len(s):]
1
nodejx 350 天前
By ChatGPT3.5:
在你的代码中,bs 是从字符串 s 创建的字节切片。当你使用 bs[len(s):] 访问超出切片有效范围的元素时,它不会导致 panic 。相反,它将返回一个空的切片,不会引发运行时错误。 因此,fmt.Println(bs[len(s):]) 这一行不会引发 panic ,它将打印一个空的字节切片 []。 但是,如果你取消注释 // fmt.Println(bs[len(s)+1:]) 这一行并尝试访问超出切片有效范围更远的元素,你会在编译时出现错误,因为你试图访问切片范围之外的元素。Go 的编译器会捕获这个错误,阻止你构建程序。 |
2
Sricor 350 天前
Go 中语法上允许 arr[len(arr):],表示从 arr 的末尾到末尾的切片,实际上返回一个空切片,且仍然与原始切片共享底层数组。
即使语法是允许的,但好像平常很少用到。 |
3
mainjzb 350 天前
没问题。返回长度是 0 的数组实际中很有用。
|
4
0o0O0o0O0o 350 天前
因为这个语法并不是去访问具体的元素吧,bs[len(bs):] 相当于 bs[len(bs):len(bs):cap(bs)] ,每个值只要不比后一个大且不比 cap 大就合法
|
5
Ericcccccccc 350 天前
是不是把 java 里的思路带过来了.
|
6
thinkershare 350 天前
切片语法就是这么规定的,因为 slice x:y 的 xy 的有效取值范围都是 0-len(slice).
而且 slice 并不拷贝底层内存内容,只是一个简单的索引计算和指针赋值。go 的零值是一个特别特殊的东西,应该是 go 独创的一个哲学概念。 |
7
apriky 350 天前
0<=start<=end<=len
|
8
xzysaber 349 天前
其实不太懂 OP 到底想问什么。
毕竟它是切片不是数组,特性有区别,了解切片的原理就不会觉得奇怪了。 然后对于 fmt.Println(bs[len(s)+1:])这个出错,是因为:前后省略时的默认值分别是 0 和 len(bs),所以这里就成了 bs[7:6],这当然是错误的。 |
9
14 349 天前
这是切片一个很有用的特性,可以无视数组长度直接按需求切片,Python 也是这样:b'1234'[5678:] == b''
|
10
wuzhewuyou 349 天前
string 以/r 切片才爽。查询长度比想象中+1 ,最后元素为空
|
11
52funny OP 感谢大家的解答,rust ,python 切片也是这样,有了这个特性我就不需要在 s[a:],不需要对 a 进行特判了,非常有用的特性。
|