取消引用结构会返回结构的新副本吗?
Posted
技术标签:
【中文标题】取消引用结构会返回结构的新副本吗?【英文标题】:Does dereferencing a struct return a new copy of struct? 【发布时间】:2016-11-21 10:51:23 【问题描述】:为什么当我们使用 (*structObj)
引用结构时,Go 似乎返回了 structObj
的新副本,而不是返回原始 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
Go playground
【问题讨论】:
【参考方案1】:tl;dr 在 Go 中解引用(使用 *
运算符)不会复制。它返回指针指向的值。
【讨论】:
没错,虽然作业确实复制了! (请注意,对于切片和映射,它只会复制标头值,而不是实际元素,因此看起来好像没有复制)【参考方案2】:当你写作时
obj := *p
您正在复制p
指向的结构的值(*
取消引用p
)。它类似于:
var obj me = *p
所以obj
是me
类型的新变量,被初始化为*p
的值。这会导致obj
具有不同的内存地址。
注意obj
是me
类型,而p
是*me
类型。但它们是不同的值。更改obj
字段的值不会影响p
中该字段的值(除非me
结构中有一个引用类型作为字段,即切片、映射或通道。参见here和here.)。如果您想产生这种效果,请使用:
obj := p
// equivalent to: var obj *me = p
现在obj
指向与p
相同的对象。它们本身仍然有不同的地址,但在它们内部保存的是实际 me
对象的相同地址。
【讨论】:
有没有办法获得指向 p 的相同的取消引用指针?就像在 main() 函数中一样,如果我们将结构附加为切片,我们将始终必须在附加本身内部取消引用它,即 res = append(res, *p)。 这不仅仅是“创建”一个新变量,通过取消引用分配给现有变量会复制值,例如*a = *b
仍将 *b
复制到 *a
。
@jimB yap,有没有办法避免重复复制?因为基本上操作只需要处理相同的 p 结构。
@ken:我不明白你的意思。您需要某种值,因此它要么是结构值,要么是指针值。如果要引用相同的结构或避免复制,请使用指针。
@JimB 好吧,也许我想太多了;)我明白你的意思,谢谢你的回复!【参考方案3】:
不,“赋值”总是在 Go 中创建一个副本,包括对函数和方法参数的赋值。语句obj := *p
将*p
的值复制到obj
。
如果您将语句 p.color = "purple"
更改为 (*p).color = "purple"
,您将获得相同的输出,因为取消引用 p
本身不会创建副本。
【讨论】:
其实是c背景,这让我很困惑。谢谢,认为这两个答案都是正确的,并且几乎在同一时间联系到我,因此选择了更多详细信息,但也为您的答案投票!dereferencing p itself does not create a copy
这澄清了我的困惑,谢谢以上是关于取消引用结构会返回结构的新副本吗?的主要内容,如果未能解决你的问题,请参考以下文章