A1
append陷阱
引用的同一个底层数组,指向的数组一样,但是长度和容量不一样
// slice append陷阱
func a() {
x := []int{1, 2, 3}
func(arr []int) {
arr[0] = 7
arr = append(arr, 100)
arr = append(arr, 101)
fmt.Println(arr) //7 2 3 100 101
}(x)
fmt.Println(x) //7 2 3
}
range陷阱
不会无限循环?
原因:编译期将原切片或者数组赋值给一个新变量 ha,在赋值的过程中就发生了拷贝
// slice与range组合操作陷阱
func b() {
arr := []int{1, 2, 3}
//不会陷入无限循环
//底层将arr重新赋值给另一个变量
for _, v := range arr {
arr = append(arr, v)
}
fmt.Println(arr)
}
汇编展开
range赋值的正确写法
原因:同时遍历索引和元素的 range 循环时,Go 语言会额外创建一个新的 v2 变量存储切片中的元素,循环中使用的这个变量 v2 会在每一次迭代被重新赋值而覆盖,赋值时也会触发拷贝,因为在循环中获取返回变量的地址都完全相同,所以返回值一样。
正确写法:正确的做法应该是使用 &arr[i] 替代 &v
// range赋值的正确写法
func c() {
arr := []int{1, 2, 3}
newArr := []*int{}
for _, v := range arr {
fmt.Println(v)
newArr = append(newArr, &v)
}
for _, v := range newArr {
fmt.Println(*v) //3 3 3
}
}
置零的高效方式
会在编译期间做优化
// 置零的高效方式
func d() {
arr := []int{1, 2, 3}
for i, _ := range arr {
arr[i] = 0
}
}