Go语言数组指针参数传递详解:值传递与指针传递的差异
Go语言中,函数参数传递方式直接影响函数内部对数组的修改是否会反映到函数外部。本文深入探讨Go语言数组指针作为函数参数传递时的行为,并解释不同函数实现导致的结果差异。
我们将基于以下代码片段进行分析:
package main import "fmt" func main() { a := [...]int{0, 0, 0} update1(a) fmt.Println(a) // 输出:[0 0 0] update2(&a) fmt.Println(a) // 输出:[0 0 0] update3(&a) fmt.Println(a) // 输出:[0 3 0] update4(&a) fmt.Println(a) // 输出:[0 4 0] } func update1(a [3]int) { a[1] = 1 } func update2(p *[3]int) { a := *p a[1] = 2 } func update3(p *[3]int) { (*p)[1] = 3 } func update4(p *[3]int) { p[1] = 4 }
代码定义了四个函数 update1
、update2
、update3
和 update4
,它们都接收数组作为参数,但传递方式和修改方式不同,导致结果差异。
update1
函数直接接收数组。Go语言中,数组是值类型,update1
函数接收的是原数组的副本。修改副本不影响原数组,因此输出仍然是 [0 0 0]
。
update2
函数接收数组指针。然而,a := *p
将指针指向的数组复制了一份给局部变量 a
。对 a
的修改只作用于副本,不改变原数组,输出仍然是 [0 0 0]
。这与 update1
结果一致,关键在于复制操作。
update3
函数接收数组指针,并直接通过 (*p)[1] = 3
修改指针指向的数组元素。这直接修改原数组,输出为 [0 3 0]
。
update4
函数与 update3
效果相同,使用指针解引用语法糖 p[1] = 4
修改数组元素,本质上与 update3
执行相同操作,只是语法更简洁。
为了进一步解释 update2
的行为,参考以下代码:
package main import "fmt" func main() { a := [...]int{1, 2, 3} c := &a b := *c b[1] = 3 fmt.Println(a) // 输出:[1 2 3] fmt.Println(b) // 输出:[1 3 3] fmt.Printf("%pn", &a) fmt.Printf("%pn", &b) // a和b的内存地址不同 }
这段代码展示了数组复制过程,b
是 a
的副本,值相同但内存地址不同,修改 b
不影响 a
。update2
中 a := *p
的行为与 b := *c
相同。因此,update2
未直接修改原数组,而是修改了其副本。
总结:Go语言中,数组指针作为参数传递时,直接操作指针指向的内存才能修改原数组。理解数组是值类型,而数组指针指向数组的内存地址,是理解关键。