在Go语言中通过传递指针给函数来获取不同的值

7

如果我想通过传递一个指向结构体的指针来改变该指针所指向的结构体的值,我通常会通过解引用该指针来实现:

type Test struct { Value int}
func main() {
   var i Test = Test {2}
   var p *Test = &i
   f(p)
   println(i.Value)  // 4
}
func f(p *Test) {
   *p = Test{4}
}

我的问题是,为什么这段代码无法更改值。
type Test struct { Value int}
func main() {
   var i Test = Test {2}
   var p *Test = &i
   f(p)
   println(i.Value)  // 2
}
func f(p *Test) {
   // ?
   p = &Test{4}
}

而这个则可以:

type Test struct { Value int}
func main() {
   var i Test = Test {2}
   var p *Test = &i
   f(p)
   println(i.Value)  // 4
}
func f(p *Test) {
   p.Value = 4
}
1个回答

12

由于这条语句:

p = &Test{4}

只是将一个新的指针值分配给变量 p。在 f() 函数内部,p 只是一个局部变量。通过为 p 分配任何新值,您只是更改了局部变量的值,而没有更改指向的值。 f() 中的局部变量 pmain() 中的局部变量 p 没有任何关系。如果您在 f() 中更改 p,它不会更改 main() 中的 p(也不会更改指向的结构体值)。
在您的第二个示例中:
p.Value = 4

这是一个缩写,意思是:

(*p).Value = 4

这会改变指向的值,当f()返回时,你将观察到这个改变。

注意:

作为一个旁注,如果在你的main()函数中,你传递了p(一个指针的局部变量)的地址给函数f(),你可以修改main()中存储的p的地址:

func f(p **Test) {
    *p = &Test{4}
}

main()函数中调用它:

var i Test = Test{2}
var p *Test = &i
f(&p)
println(i.Value) // 2 - Note that 'i' won't change!
println(p.Value) // 4 - Only the address in 'p' to the new struct value created in f()

但显然,传递一个单一指针*Test并修改所指向的值(p.Value = 4)更为高效、方便和清晰。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接