切片切片引用

  • 本文关键字:切片 引用 go slice
  • 更新时间 :
  • 英文 :


我正在Golang网站上进行游览,我正在尝试消化其中一个例子。目前尚不清楚它是如何工作的:

package main
import "fmt"
func main() {
s := []int{2, 3, 5, 7, 11, 13}
printSlice(s)
// Slice the slice to give it zero length.
s = s[:0]
printSlice(s)
// Extend its length.
s = s[:4]
printSlice(s)
// Drop its first two values.
s = s[2:]
printSlice(s)
}
func printSlice(s []int) {
fmt.Printf("len=%d cap=%d %vn", len(s), cap(s), s)
}

输出为:

len=6 cap=6 [2 3 5 7 11 13]
len=0 cap=6 []
len=4 cap=6 [2 3 5 7]
len=2 cap=4 [5 7]

在第一个切片之后,s = s[:0]切片长度为 0。然后还有另一块s = s[:4].虽然长度为 0,但这似乎有效。但是这是怎么发生的呢?底层阵列不应该从s访问吗?

更让我困惑的是,下次我们切片时,s = s[2:]我们切片的是 s 的旧值(即 4 个元素(而不是原始数组

有人可以说出一些线索吗 两种情况有什么区别?

切片基本上是指向内存的指针,其中包含一些附加信息:

1(当前使用的元素数量和

2(容量,即它可以占用的剩余长度。

一开始,我们创建一个包含 6 个整数的切片,这使得创建总大小为 6 的底层 int 数组。

here is your memory locations with addresses (content does not matter here)
*  *  *  *  *  *
[0][1][2][3][4][5]
^
s points to the start of the memory
len(s) = 6
cap(s) = 6

接下来我们说:使这个切片的len为 0,这是在位置 0 处取一个长度为 0 的s子切片的s = s[:0]。请注意,s[0:0]相同,则可以省略前 0。

[0][1][2][3][4][5]
^
s still points to the start of the memory
len(s) = 0
cap(s) = 6

由于容量仍然相同,我们不妨通过说 4 来制作长度s = s[:4].

*  *  *  *
[0][1][2][3][4][5]
^
s still points to the start of the memory
len(s) = 4
cap(s) = 6

然后我们通过执行s = s[2:].

*  *
[0][1][2][3][4][5]
^
s now points to the original address plus two!
len(s) = 2
cap(s) = 4

Leon向我介绍了Go的博客文章,他们准确地解决了我的问题。

这是帮助我更好地理解这个概念的片段:

切片是数组段的描述符。它由指向数组的指针、段的长度及其容量(段的最大长度(组成。

切片不能超出其容量。尝试这样做会导致运行时崩溃,就像在切片或数组边界之外编制索引一样。同样,切片不能重新切片到零以下以访问数组中的早期元素。

如果数组中有更多元素,则可以扩展切片,但它无法访问切片 0 以下的元素。它是底层阵列的窗口。博客文章对此进行了更深入的解释。