说明
因为slice是指针类型,所以很多人会误以为其传递的是引用,所以在使用的过程中会出现一些非期望的实现。
问题
在使用append函数时,比如以下函数:
func sliceModify(slice []int) {
// slice[0] = 88
slice = append(slice, 6)
}
func main() {
slice := []int{1, 2, 3, 4, 5}
sliceModify(slice)
fmt.Println(slice)
}
// [1 2 3 4 5]
为什么append的数组在外部没有改变呢,因为slice传的是值,虽然改变了底层数据,但是外部slice的状态并没改变。也许有人质疑值语义,但是有以下代码
func modifySlice(data []int) {
data = nil
}
func main() {
a := []int{1,2,3}
fmt.Println(a)
modifySlice(a)
fmt.Println(a)
}
// [1, 2, 3]
// [1, 2, 3]
从上面代码可以看到,改变slice本身的值并不会改变外部的值,及是值语义。
那么如何解决值传递带来的问题,解决方法一,就是将slice作为指针传递:
func sliceModify(slice *[]int) {
*slice = append(*slice, 6)
}
func main() {
slice := []int{1, 2, 3, 4, 5}
sliceModify(&slice)
fmt.Println(slice)
}
指针会改变原本变量的状态,所以外部的slice发生了改变。
另一种解决方法是改变外部变量的状态,如下代码:
func main() {
s1 := make([] int ,3,5)
s1[0] = 1
s1[1] = 2
fmt.Println(s1)
s2 :=s1[:4]
}
func test( s [] int ) {
s = append(s,3)
fmt.Println(s)
}
//[1 2 0 3]
//[1 2 0]
//[1 2 0 3]
虽然在函数内修改slice但是只是添加到了内存中,所以在函数中内printf出来,但是外部的len没有改变,所以不会显示,如果强制改变其状态,那么添加的值也就显露出来了。