切片参考

Che*_* A. 1 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 %v\n", len(s), cap(s), s)
}
Run Code Online (Sandbox Code Playgroud)

输出是:

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]
Run Code Online (Sandbox Code Playgroud)

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

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

有人可以解决这两种情况之间的区别吗?

gon*_*utz 5

切片基本上是指向内存的指针,带有一些附加信息:

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
Run Code Online (Sandbox Code Playgroud)

接下来我们说:使这个切片len为0,这是s = s[:0]一个s位于0的长度为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
Run Code Online (Sandbox Code Playgroud)

由于容量仍然相同,我们不妨说长度为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
Run Code Online (Sandbox Code Playgroud)

然后我们通过执行一个不在内存开头处开始的子切片s = s[2:].

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