对于 Go 切片有点疑问?

163 天前
 52funny

为什么切片的左边可以是数组的长度,按照道理来说应该越界了呀?

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):]

Code

2184 次点击
所在节点    Go 编程语言
11 条回复
nodejx
163 天前
By ChatGPT3.5:

在你的代码中,bs 是从字符串 s 创建的字节切片。当你使用 bs[len(s):] 访问超出切片有效范围的元素时,它不会导致 panic 。相反,它将返回一个空的切片,不会引发运行时错误。

因此,fmt.Println(bs[len(s):]) 这一行不会引发 panic ,它将打印一个空的字节切片 []。

但是,如果你取消注释 // fmt.Println(bs[len(s)+1:]) 这一行并尝试访问超出切片有效范围更远的元素,你会在编译时出现错误,因为你试图访问切片范围之外的元素。Go 的编译器会捕获这个错误,阻止你构建程序。
Sricor
163 天前
Go 中语法上允许 arr[len(arr):],表示从 arr 的末尾到末尾的切片,实际上返回一个空切片,且仍然与原始切片共享底层数组。

即使语法是允许的,但好像平常很少用到。
mainjzb
163 天前
没问题。返回长度是 0 的数组实际中很有用。
0o0O0o0O0o
163 天前
因为这个语法并不是去访问具体的元素吧,bs[len(bs):] 相当于 bs[len(bs):len(bs):cap(bs)] ,每个值只要不比后一个大且不比 cap 大就合法
Ericcccccccc
163 天前
是不是把 java 里的思路带过来了.
thinkershare
162 天前
切片语法就是这么规定的,因为 slice x:y 的 xy 的有效取值范围都是 0-len(slice).
而且 slice 并不拷贝底层内存内容,只是一个简单的索引计算和指针赋值。go 的零值是一个特别特殊的东西,应该是 go 独创的一个哲学概念。
apriky
162 天前
0<=start<=end<=len
xzysaber
162 天前
其实不太懂 OP 到底想问什么。
毕竟它是切片不是数组,特性有区别,了解切片的原理就不会觉得奇怪了。
然后对于 fmt.Println(bs[len(s)+1:])这个出错,是因为:前后省略时的默认值分别是 0 和 len(bs),所以这里就成了 bs[7:6],这当然是错误的。
14
162 天前
这是切片一个很有用的特性,可以无视数组长度直接按需求切片,Python 也是这样:b'1234'[5678:] == b''
wuzhewuyou
162 天前
string 以/r 切片才爽。查询长度比想象中+1 ,最后元素为空
52funny
161 天前
感谢大家的解答,rust ,python 切片也是这样,有了这个特性我就不需要在 s[a:],不需要对 a 进行特判了,非常有用的特性。

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/997051

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX