Q 群里讨论起来 slice 的传递,才发现有坑 = =
看了网上的一些文章。slice 在传入函数后 append 会有坑 下面是我的理解,不知道恰不恰当。
一种情况是 cap 够,不扩容
func main() {
sliceA := make([]int, 3, 4)
sliceA[0] = 0
sliceA[1] = 1
sliceA[2] = 2
fmt.Println(sliceA)
changeSlice(sliceA)
fmt.Println(sliceA)
fmt.Println(sliceA[:4])
}
func changeSlice(slicePass []int) {
slicePass = append(slicePass, 3)
}
//Output
/*
[0 1 2]
[0 1 2]
[0 1 2 3]
*/
slice 结构中的 len,cap 都是 int,无法在函数里面被改变。 这种情况下指定了一个 len 为 3,cap 为 4 的 slice 。append 完后发现正常输出只会输出前三个数,验证了 len 并没有被改变。而当强制输出第四项时又发现 3 是存在的。 例如截取数组等操作都是这种情况。
也就是说这种情况下 append 对原数组生效,只是由于 len 没有改变而无法呈现出 append 的项。
还有种情况是 cap 不够,slice 扩容
slice 扩容会把扩容后的数组指向新内存,直接与原数组无关了,append 的项也不存在于原数组 大概代码长这样
func main() {
sliceA := []int{1, 2, 3, 4, 5}
fmt.Println(sliceA)
fmt.Printf("%d %p main\n", len(sliceA),sliceA)
changeSliceA(sliceA)
fmt.Println(sliceA)
}
func changeSliceA(slicePass []int) {
slicePass = append(slicePass, 6)
fmt.Printf("%d %p pass\n", len(slicePass),slicePass)
}
// Output
/*
[1 2 3 4 5]
5 0xc00000c690 main
6 0xc000016550 pass
[1 2 3 4 5]
*/
所以是 go 中的 slice 在函数中被 append 时数据呈现不变分为两种情况。
一种是 len 未被改变,由传值导致;
一种是指针发生改变,由 slice 的内部扩容实现导致?
这样理解有没有问题?
这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。
V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。
V2EX is a community of developers, designers and creative people.