取消引用结构 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

Go playground

写的时候

obj := *p

您正在复制 p 指向的结构的值(* 取消引用 p)。它类似于:

var obj me = *p

所以obj是一个me类型的新变量,被初始化为*p的值。这导致 obj 具有不同的内存地址。

注意 objme 类型,而 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 指针指向的值。