V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
The Go Programming Language
http://golang.org/
Go Playground
Go Projects
Revel Web Framework
52funny
V2EX  ›  Go 编程语言

对于 Go 切片有点疑问?

  •  
  •   52funny · 2023-12-02 11:20:26 +08:00 · 2392 次点击
    这是一个创建于 380 天前的主题,其中的信息可能已经有所发展或是发生改变。

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

    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

    11 条回复    2023-12-04 09:54:07 +08:00
    nodejx
        1
    nodejx  
       2023-12-02 11:44:11 +08:00
    By ChatGPT3.5:

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

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

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

    即使语法是允许的,但好像平常很少用到。
    mainjzb
        3
    mainjzb  
       2023-12-02 12:21:10 +08:00
    没问题。返回长度是 0 的数组实际中很有用。
    0o0O0o0O0o
        4
    0o0O0o0O0o  
       2023-12-02 12:25:01 +08:00
    因为这个语法并不是去访问具体的元素吧,bs[len(bs):] 相当于 bs[len(bs):len(bs):cap(bs)] ,每个值只要不比后一个大且不比 cap 大就合法
    Ericcccccccc
        5
    Ericcccccccc  
       2023-12-02 15:02:07 +08:00
    是不是把 java 里的思路带过来了.
    thinkershare
        6
    thinkershare  
       2023-12-02 18:16:26 +08:00
    切片语法就是这么规定的,因为 slice x:y 的 xy 的有效取值范围都是 0-len(slice).
    而且 slice 并不拷贝底层内存内容,只是一个简单的索引计算和指针赋值。go 的零值是一个特别特殊的东西,应该是 go 独创的一个哲学概念。
    apriky
        7
    apriky  
       2023-12-02 21:33:58 +08:00
    0<=start<=end<=len
    xzysaber
        8
    xzysaber  
       2023-12-03 09:22:53 +08:00
    其实不太懂 OP 到底想问什么。
    毕竟它是切片不是数组,特性有区别,了解切片的原理就不会觉得奇怪了。
    然后对于 fmt.Println(bs[len(s)+1:])这个出错,是因为:前后省略时的默认值分别是 0 和 len(bs),所以这里就成了 bs[7:6],这当然是错误的。
    14
        9
    14  
       2023-12-03 10:36:19 +08:00
    这是切片一个很有用的特性,可以无视数组长度直接按需求切片,Python 也是这样:b'1234'[5678:] == b''
    wuzhewuyou
        10
    wuzhewuyou  
       2023-12-03 12:47:03 +08:00
    string 以/r 切片才爽。查询长度比想象中+1 ,最后元素为空
    52funny
        11
    52funny  
    OP
       2023-12-04 09:54:07 +08:00
    感谢大家的解答,rust ,python 切片也是这样,有了这个特性我就不需要在 s[a:],不需要对 a 进行特判了,非常有用的特性。
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   3029 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 22ms · UTC 00:42 · PVG 08:42 · LAX 16:42 · JFK 19:42
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.