取消引用结构 return 是否是结构的新副本?
Does dereferencing a struct return a new copy of struct?
为什么当我们使用 (*structObj)
引用结构时,Go 似乎 return structObj
的新副本而不是 return 原始 structObj
的相同地址]?这可能是我的一些误解,所以我寻求澄清
package main
import (
"fmt"
)
type me struct {
color string
total int
}
func study() *me {
p := me{}
p.color = "tomato"
fmt.Printf("%p\n", &p.color)
return &p
}
func main() {
p := study()
fmt.Printf("&p.color = %p\n", &p.color)
obj := *p
fmt.Printf("&obj.color = %p\n", &obj.color)
fmt.Printf("obj = %+v\n", obj)
p.color = "purple"
fmt.Printf("p.color = %p\n", &p.color)
fmt.Printf("p = %+v\n", p)
fmt.Printf("obj = %+v\n", obj)
obj2 := *p
fmt.Printf("obj2 = %+v\n", obj2)
}
输出
0x10434120
&p.color = 0x10434120
&obj.color = 0x10434140 //different than &p.color!
obj = {color:tomato total:0}
p.color = 0x10434120
p = &{color:purple total:0}
obj = {color:tomato total:0}
obj2 = {color:purple total:0} // we get purple now when dereference again
写的时候
obj := *p
您正在复制 p
指向的结构的值(*
取消引用 p
)。它类似于:
var obj me = *p
所以obj
是一个me
类型的新变量,被初始化为*p
的值。这导致 obj
具有不同的内存地址。
注意 obj
是 me
类型,而 p
是 *me
类型。但它们是不同的值。更改 obj
字段的值不会影响 p
中该字段的值(除非 me
结构中有引用类型作为字段,即 slice、map 或频道。参见 and here。)。如果你想带来那种效果,使用:
obj := p
// equivalent to: var obj *me = p
现在 obj
指向与 p
相同的对象。它们本身仍然有不同的地址,但在它们内部包含实际 me
对象的相同地址。
不,"assignment" 总是在 Go 中创建一个副本,包括对函数和方法参数的赋值。语句 obj := *p
将 *p
的值复制到 obj
。
如果将语句 p.color = "purple"
更改为 (*p).color = "purple"
,您将获得相同的输出,因为取消引用 p
本身不会创建副本。
tl;dr 在 Go 中取消引用(使用 *
运算符)不会创建副本。它 returns 指针指向的值。
为什么当我们使用 (*structObj)
引用结构时,Go 似乎 return structObj
的新副本而不是 return 原始 structObj
的相同地址]?这可能是我的一些误解,所以我寻求澄清
package main
import (
"fmt"
)
type me struct {
color string
total int
}
func study() *me {
p := me{}
p.color = "tomato"
fmt.Printf("%p\n", &p.color)
return &p
}
func main() {
p := study()
fmt.Printf("&p.color = %p\n", &p.color)
obj := *p
fmt.Printf("&obj.color = %p\n", &obj.color)
fmt.Printf("obj = %+v\n", obj)
p.color = "purple"
fmt.Printf("p.color = %p\n", &p.color)
fmt.Printf("p = %+v\n", p)
fmt.Printf("obj = %+v\n", obj)
obj2 := *p
fmt.Printf("obj2 = %+v\n", obj2)
}
输出
0x10434120
&p.color = 0x10434120
&obj.color = 0x10434140 //different than &p.color!
obj = {color:tomato total:0}
p.color = 0x10434120
p = &{color:purple total:0}
obj = {color:tomato total:0}
obj2 = {color:purple total:0} // we get purple now when dereference again
写的时候
obj := *p
您正在复制 p
指向的结构的值(*
取消引用 p
)。它类似于:
var obj me = *p
所以obj
是一个me
类型的新变量,被初始化为*p
的值。这导致 obj
具有不同的内存地址。
注意 obj
是 me
类型,而 p
是 *me
类型。但它们是不同的值。更改 obj
字段的值不会影响 p
中该字段的值(除非 me
结构中有引用类型作为字段,即 slice、map 或频道。参见
obj := p
// equivalent to: var obj *me = p
现在 obj
指向与 p
相同的对象。它们本身仍然有不同的地址,但在它们内部包含实际 me
对象的相同地址。
不,"assignment" 总是在 Go 中创建一个副本,包括对函数和方法参数的赋值。语句 obj := *p
将 *p
的值复制到 obj
。
如果将语句 p.color = "purple"
更改为 (*p).color = "purple"
,您将获得相同的输出,因为取消引用 p
本身不会创建副本。
tl;dr 在 Go 中取消引用(使用 *
运算符)不会创建副本。它 returns 指针指向的值。