请大家猜猜打印x和y的内容会是什么?以及想想为什么会这样子?其中的知识点有哪些?
package main
import (
"fmt"
)
func main() {
x := []int{1, 2, 3}
y := x[:2]
y = append(y, 10)
fmt.Println("x=", x, &x[0])
fmt.Println("y=", y, &y[0])
y = append(y, 20)
fmt.Println("y=", y, &y[0])
y[0] = 20
for i := 0; i < 10; i++ {
y = append(y, i)
}
fmt.Println("y=", y, &y[0])
}
package main
import (
"fmt"
)
func main() {
x := []int{1, 2, 3}
y := x[:2]//【1】
y = append(y, 10)//【2】
fmt.Println("x=", x, &x[0]) //x= [1 2 10] 0xc0000b6020
fmt.Println("y=", y, &y[0]) //y= [1 2 10] 0xc0000b6020
y = append(y, 20)//【3】
fmt.Println("y=", y, &y[0]) //y= [1 2 10 20] 0xc0000ac030
y[0] = 20//【4】
for i := 0; i < 10; i++ {
y = append(y, i)
}
fmt.Println("y=", y, &y[0]) //y= [20 2 10 20 0 1 2 3 4 5 6 7 8 9] 0xc0000ba000 【5】
}
}
slice 的数据结构,一个指向真实 array 地址的指针 ptr ,slice 的长度 len 和容量 cap ,在底层数组容量不足时可以实现自动重分配并生成新的Slice,在实际使用中,我们最好事先预期好一个cap,这样在使用append的时候可以避免反复重新分配内存复制之前的数据,减少不必要的性能消耗。
data = append(data, i)
data= [0] 0xc0000b4008 //【1】初始化地址
data= [0 1] 0xc0000b4030 //【2】第一次扩容+1,地址改变
i=%d,data=%v
0 0xc0000b6040 //【3】第二次扩容+2,地址改变
i=%d,data=%v
1 0xc0000b6040 //Slice容量够用,则将新元素追加进去,Slice.len++,返回原Slice
i=%d,data=%v
2 0xc0000ba000 //【4】第三次扩容+4,地址改变
i=%d,data=%v
3 0xc0000ba000 //Slice容量够用,则将新元素追加进去,Slice.len++,返回原Slice
i=%d,data=%v
4 0xc0000ba000 //同上
i=%d,data=%v
5 0xc0000ba000 //同上
i=%d,data=%v
6 0xc0000bc000 //【5】第四次扩容+8,地址改变
i=%d,data=%v
7 0xc0000bc000 //同上
i=%d,data=%v
8 0xc0000bc000 //同上
i=%d,data=%v
9 0xc0000bc000 //同上
扩容容量的选择遵循以下规则:
如果原Slice容量小于1024,则新Slice容量将扩大为原来的2倍 如果原Slice容量大于等于1024,则新Slice容量将扩大为原来的1.25倍
创建切片时可根据实际需要预分配容量,尽量避免追加过程中扩容操作(append),有利于提升性能
Golang语言slice实现原理及使用方法
golang slice 切片原理