我正在浏览Go,想知道以下内容:
package main
import "fmt"
func main() {
s := []int{2, 3, 5, 7, 11, 13}
printSlice(s)
// Drop its last two values
s = s[:len(s)-2]
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)
}
结果:
len=6 cap=6 [2 3 5 7 11 13]
len=4 cap=6 [2 3 5 7]
len=2 cap=4 [5 7]
为什么在丢弃最后2个项目时切片的容量保持不变,而在丢弃前2个项目时却改变了?
答案 0 :(得分:5)
Go slice被实现为一个结构:
src/runtime/slice.go
:
type slice struct {
array unsafe.Pointer
len int
cap int
}
修改您的printSlice
函数以显示指向基础数组的指针:
package main
import "fmt"
func main() {
s := []int{2, 3, 5, 7, 11, 13}
printSlice(s)
// Drop its last two values
s = s[:len(s)-2]
printSlice(s)
// Drop its first two values.
s = s[2:]
printSlice(s)
}
func printSlice(s []int) {
var ptr *int
if cap(s) >= 1 {
ptr = &s[:cap(s)][0]
}
fmt.Printf("ptr=%p len=%d cap=%d %v\n", ptr, len(s), cap(s), s)
}
游乐场:https://play.golang.org/p/pk3cpE_LsUV
输出:
ptr=0x450000 len=6 cap=6 [2 3 5 7 11 13]
ptr=0x450000 len=4 cap=6 [2 3 5 7]
ptr=0x450008 len=2 cap=4 [5 7]
查看切片操作如何调整指针,长度和容量。切片只是基础数组的视图或窗口。
参考文献:
答案 1 :(得分:0)
切片在封面下有一个缓冲区。容量是该缓冲区的大小。从末尾删除项目不会更改缓冲区大小。
您正在从现有切片中创建一个新切片,但是从2开始新切片的索引。新切片仍指向相同的基础缓冲区(但偏移量为2)。因此,此新切片的缓冲区大小(和容量)要少2。
当您看到追加的工作原理时,容量才有意义。 Append尝试重用相同的基础缓冲区-但如果容量已满,则会执行重新分配和复制。