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

Yar*_*Yar 5 struct pointers go

假设我想传递一个指向函数的指针,并通过这样做来改变该指针指向的结构的值.我通常会通过取消引用指针来做到这一点:

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}
}
Run Code Online (Sandbox Code Playgroud)

我的问题是,为什么这段代码不会改变价值

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}
}
Run Code Online (Sandbox Code Playgroud)

虽然这个做了:

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
}
Run Code Online (Sandbox Code Playgroud)

icz*_*cza 12

因为这行:

p = &Test{4}
Run Code Online (Sandbox Code Playgroud)

只需为p变量指定一个新的指针值.在f()函数内部,p只是一个局部变量.通过分配任何新值p,您只需更改局部变量的值而不是指向的值.

p在局部变量f()无关,与p在本地变量main().如果你改变pf(),它不会改变pmain()(这也不会改变尖结构值).

在你的第二个例子中:

p.Value = 4
Run Code Online (Sandbox Code Playgroud)

这是一个简写:

(*p).Value = 4
Run Code Online (Sandbox Code Playgroud)

这会改变指向的值,因此您将在f()返回时观察到更改.

注意:

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

func f(p **Test) {
    *p = &Test{4}
}
Run Code Online (Sandbox Code Playgroud)

从中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()
Run Code Online (Sandbox Code Playgroud)

但显然传递单个指针*Test并修改指向值(p.Value = 4)更有效,更方便,更清晰.