我试图在a := b
中找出a
是否是结构的不同副本,例如func pass_by_value(a some_struct)
但是我发现我不明白打印语句。
考虑这个go playground
nested_level2 := test_assign_nested_level2{}
nested_level1 := test_assign_nested{nested_level2}
top_level := test_assign{nested_level1}
assign := top_level
fmt.Println("top_level address")
fmt.Printf("%p", &top_level)
fmt.Println(" ")
fmt.Println("1 level address")
fmt.Printf("%p", &top_level.Level1)
fmt.Println(" ")
fmt.Println("2 level address")
fmt.Printf("%p", &top_level.Level1.Level_2)
fmt.Println("------------------------")
fmt.Println("assign top_level address")
fmt.Printf("%p", &assign)
fmt.Println(" ")
fmt.Println("1 level address")
fmt.Printf("%p", &assign.Level1)
fmt.Println(" ")
fmt.Println("2 level address")
fmt.Printf("%p", &assign.Level1.Level_2)
上面的输出是
top_level address
0x10410020
1 level address
0x10410020
2 level address
0x10410020
assign top_level address
0x10410024
1 level address
0x10410024
2 level address
0x10410024
我希望输出类似于
fmt.Println("top_level address")
fmt.Printf("%p", &top_level)
fmt.Println(" ")
fmt.Println("1 level address")
fmt.Printf("%p", &nested_level1)
fmt.Println(" ")
fmt.Println("2 level address")
fmt.Printf("%p", &nested_level2)
fmt.Println(" ")
fmt.Println(" ------------------------------- ")
哪里
top_level address
0x421152280
1 level address
0x421152270
2 level address
0x421152260
每个结构体都有不同的地址。但子结构似乎与父结构具有相同的地址。
为什么结构体中的所有嵌套元素都有相同的地址?
:=
实际上会递归地复制一个新的 struct
吗?就像打印语句所示的那样? (即 :=
将返回一个全新的结构副本,其每个字段内容也是递归的全新副本)
最佳答案
Go 中的类型不是其他事物的自主包装器,而只是两件事:类型允许附加方法,类型提供内存中的布局。对于这里的问题,将方法附加到类型的能力是无关紧要的。让我们看一下这个问题的中立表述:
type A int64
type B { a A }
type C { b B }
这声明了具有以下内存布局的三种类型:
- 类型 A 具有 int64 的内存布局(即 8 个字节)。
- 类型 B 具有单个 A 的内存布局,即 int64,即 8 个字节。
- C 型具有单个 B 的内存布局,即单个 A,即 int64,因此 8 个字节。
关于内存布局,B 类型不是 A 的“包装器”,至少包装器绝对没有添加任何内容。从纯粹的内存布局角度来看,定义类型 B 是没有用的(但它允许将不同的方法附加到 B 而不是 A)。
现在应该清楚了,c C
的地址是其 8 个字节中的第一个字节,这与 c.b 的地址相同,而 c.b.a 的地址也相同。对 C 的任何赋值都只是一个机器字的副本(在 64 位架构上)。
如果您定义type D { a A; b B }
它变得更有趣,因为 D 现在是 16 字节长。 (向 D 添加更多内容甚至可能会因填充而留下漏洞。)但是 D 仍然没有为内存中彼此相邻的 A 和 B 提供任何内容(期望新的方法集)。
关于pointers - 为什么所有嵌套的结构体对象在打印出来时都有相同的地址?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46313250/