我正在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个元素),而不是原始数组.
有人可以解决这两种情况之间的区别吗?
切片基本上是指向内存的指针,带有一些附加信息:
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)