Golang中对slice进行append时需要注意

2,652 阅读1分钟

先上一段代码,试想象一下打印arr的结果

a := arr[0:2]
a1 := append(a, 1)
a2 := append(a1, 2)
a3 := append(a1, 3)
log.Println(arr)

众所周知,slice的底层是一个struct,有arrPtr、len、cap三个属性,其中arrPtr指向一个数组,接下来让我们把arr打印出来看看

[0 0 1 3 ]

为什么是[0, 0, 1, 3],第4行append的2哪去了?

综合分析代码以及行为我们可以得出结论,当cap充足时,append会在slice对应的数组下标后面,直接添加元素,即使该位置是非零的,也会覆盖赋值。基于这个结论,我们再来看一下a1,a2,a3

arr := [4]int{0, 0}
a := arr[0:2]
a1 := append(a, 1)
a2 := append(a1, 2)
a3 := append(a1, 3)
log.Println(arr)//[0 0 1 3]
log.Println(a2)//[0 0 1 3]
log.Println(a3)//[0 0 1 3]

很显然,有些业务场景中,我们希望a2的值能独立出来,不要再依赖于a1,此时可以用一个copy

arr := [4]int{0, 0}
a := arr[0:2]
a1 := append(a, 1)
a2 := make([]int, len(a1))
copy(a2, a1)
a2 = append(a2, 2)
a3 := append(a1, 3)
log.Println(arr) //[0 0 1 3]
log.Println(a2)  //[0 0 1 2]
log.Println(a3)  //[0 0 1 3]

如果你希望有一个自由的slice,那么请为他准备一个独享的arr