go-questions icon indicating copy to clipboard operation
go-questions copied to clipboard

切片作为函数参数这一章节,倒数第三段描述应该不准确

Open hookokoko opened this issue 3 years ago • 1 comments

问题描述

请在此描述你的问题,提问前请参考提问的智慧

原文是这么说的:

myAppend 函数里,虽然改变了 s,但它只是一个值传递,并不会影响外层的 s,因此第一行打印出来的结果仍然是 [1 1 1]。

这个地方我在第一次看到的时候有点歧义,虽说slice是一个值传递,但是slice中是包含是指向数组的指针的。按理说,值传递的也是数组的指针。

经过验证,不影响的准确原因应该是append触发了slice的扩容,扩容会导致copy,也就是说slice结构体中指向数组的指针发生了变化。因此外层的s不会发生变化。 如果是直接修改slice元素,内外层都会改变

func myAppend(s []int) []int {
	//s = append(s, 100)
	s[0] = 100
	fmt.Printf("s point out func: %p, %p\n", s, &s)
	return s
}

我个人的理解,如有不对,欢迎讨论~

hookokoko avatar Jun 11 '22 02:06 hookokoko

这里的描述也感觉有点歧义。

果真改变了原始 slice 的底层数据。这里传递的是一个 slice 的副本,在 f 函数中,s 只是 main 函数中 s 的一个拷贝。在f 函数内部,对 s 的作用并不会改变外层 main 函数的 s。 但就结果来看,对 f函数内s 的作用改变了外层 main 函数的 s。 我理解其实传的不是slice的副本,而是slice指针的副本,因为slice本身就是引用类型变量,所以在f函数中修改s的值,slice的值也被修改。

func main() {
	slice := []int{0, 1, 2, 3, 4, 5, 6, 7, 8, 9}
	fmt.Printf("%p\n", slice)
	f(slice)
}
func f(s []int) {
	fmt.Printf("%p\n", s)
}

输出的结果:

0x1400001c0f0
0x1400001c0f0

ricky-zhf avatar Jan 29 '23 13:01 ricky-zhf