有个难题请教一下大家,slice 切片扩容导致的问题
网上看到了一篇文章,里面有一个很有意思的问题,但是解释的不是很明白,我在网上也没找到解答,所以在这里想请教一下大家,感谢!
package main
import "fmt"
func main() {
s3 := make([]int, 2, 10)
fmt.Println(s3) // [0 0]
Test2(s3)
fmt.Println(s3) // [0 0]
s4 := s3[0:10]
s4[0] = 100
fmt.Println(s3) // [100 0]
fmt.Println(s4) // [100 0 6 6 6 0 0 0 0 0]
}
func Test2(s []int) {
s = append(s, 6)
s = append(s, 6)
s = append(s, 6)
fmt.Println(s) // [0 0 6 6 6]
}
得出的结果是:
[0 0]
[0 0 6 6 6]
[0 0]
[100 0]
[100 0 6 6 6 0 0 0 0 0]
不太明白,第三个结果为什么是[0 0],而不是 [0 0 6 6 6] 呢
在Test2 函数中,使用append的时候,并没有扩容,添加的数据还在底层数组的容量中, 那为啥在 Test2函数之后 s3是[0 0], s4:=s3[0:10] 是[100 0 6 6 6 0 0 0 0 0],为什么不是[100, 0]呢,修改了s4[0]的值,s3的第一个值也变成了100.
想了很久都没找到答案
关于 LearnKu
因为你这个是值传递参数的方式,只是将s3当作值传递给了Test2。如果你使用引用传递参数的方式,也就是将Test2更改为
func Test2(s *[]int)这种,那么你就可以得到你上面疑问的答案。这个是因为切片赋值操作是浅拷贝的方式,s3和s4其实还是共享同一个内存地址,那么修改s4的内部会导致s3的内部一并被改动。
fmt.Printf("s3 addr: %p, s4 addr: %p\n", s3, s4)你可以看到他们的地址其实是相同的。可以看看这篇文章: yuminlee2.medium.com/golang-deep-a...