Golang Go语言中对切片有点疑问?

发布于 1周前 作者 zlyuanteng 来自 Go语言

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

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


Golang Go语言中对切片有点疑问?

更多关于Golang Go语言中对切片有点疑问?的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html

12 回复

By ChatGPT3.5:

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

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

但是,如果你取消注释 // fmt.Println(bs[len(s)+1:]) 这一行并尝试访问超出切片有效范围更远的元素,你会在编译时出现错误,因为你试图访问切片范围之外的元素。Go 的编译器会捕获这个错误,阻止你构建程序。

更多关于Golang Go语言中对切片有点疑问?的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


Go 中语法上允许 arr[len(arr):],表示从 arr 的末尾到末尾的切片,实际上返回一个空切片,且仍然与原始切片共享底层数组。

即使语法是允许的,但好像平常很少用到。

没问题。返回长度是 0 的数组实际中很有用。

因为这个语法并不是去访问具体的元素吧,bs[len(bs):] 相当于 bs[len(bs):len(bs):cap(bs)] ,每个值只要不比后一个大且不比 cap 大就合法

是不是把 java 里的思路带过来了.

切片语法就是这么规定的,因为 slice x:y 的 xy 的有效取值范围都是 0-len(slice).
而且 slice 并不拷贝底层内存内容,只是一个简单的索引计算和指针赋值。go 的零值是一个特别特殊的东西,应该是 go 独创的一个哲学概念。

0<=start<=end<=len

其实不太懂 OP 到底想问什么。
毕竟它是切片不是数组,特性有区别,了解切片的原理就不会觉得奇怪了。
然后对于 fmt.Println(bs[len(s)+1:])这个出错,是因为:前后省略时的默认值分别是 0 和 len(bs),所以这里就成了 bs[7:6],这当然是错误的。

这是切片一个很有用的特性,可以无视数组长度直接按需求切片,Python 也是这样:b’1234’[5678:] == b’’

string 以/r 切片才爽。查询长度比想象中+1 ,最后元素为空

感谢大家的解答,rust ,python 切片也是这样,有了这个特性我就不需要在 s[a:],不需要对 a 进行特判了,非常有用的特性。

在Go语言中,切片(slice)是一个相当强大且灵活的数据结构,它基于数组构建,但提供了更动态的内存管理能力。以下是对切片的一些常见疑问及其解答:

  1. 切片是什么? 切片是对数组的抽象和封装,它包含了指向数组起始元素的指针、切片的长度以及切片的容量(即底层数组可用的最大元素数)。

  2. 如何创建切片? 可以通过字面量、make函数或切割已有数组来创建切片。例如:

    s := []int{1, 2, 3}
    s2 := make([]int, 5)
    s3 := s[1:3]
    
  3. 切片是引用类型吗? 是的,切片是引用类型,传递切片时实际上传递的是对底层数组的引用。因此,对切片所做的修改会影响到其他引用该数组的切片。

  4. 切片会自动扩容吗? 当向切片添加元素导致其容量不足时,Go会自动为其分配更大的底层数组并复制原有元素,但这会导致性能开销。因此,最好预估切片的大小并提前分配足够的容量。

  5. 切片与数组的区别? 数组具有固定长度,而切片则具有动态长度。数组直接存储数据,而切片是对数组的抽象和封装,提供了更灵活的操作方式。

希望这些解答能帮助你更好地理解Go语言中的切片。如果有更多问题,欢迎继续提问!

回到顶部