我想在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
?像印刷声明所示? (即。:=
将返回一个全新的struct副本,其每个字段内容也是递归的全新副本)
答案 0 :(得分:3)
Go中的类型不是围绕其他事物的autonomes包装器,而只是两件事:类型允许附加方法和类型在内存中提供布局。对于这里的问题,将方法附加到类型的能力是无关紧要的。让我们来看看这个问题的中性表述:
type A int64
type B { a A }
type C { b B }
这声明了三种具有以下内存布局的类型:
关于内存布局的类型B是不 a"包装"在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提供任何内容(期望新的方法集)。
答案 1 :(得分:1)
我的猜测是你正在寻找这样的东西:
package main
import "fmt"
// Nesting: type T2 struct{ F3 int }
type T2 struct{ F3 int }
// Nesting: type T1 struct{ { F2 struct{ F3 int } }
type T1 struct{ F2 T2 }
// Nesting: type T0 struct{ F1 struct{ F2 struct{ F3 int } } }
type T0 struct{ F1 T1 }
func main() {
t2 := T2{F3: 42}
fmt.Printf(
"%p %p %d\n",
// 0xc4200120d0 0xc4200120d0 42
&t2, &t2.F3, t2.F3,
)
t1 := T1{F2: t2}
fmt.Printf(
"%p %p %p %d\n",
// 0xc4200120f0 0xc4200120f0 0xc4200120f0 42
&t1, &t1.F2, &t1.F2.F3, t1.F2.F3,
)
t0 := T0{F1: t1}
fmt.Printf(
"%p %p %p %p %d\n",
// 0xc420012100 0xc420012100 0xc420012100 0xc420012100 42
&t0, &t0.F1, &t0.F1.F2, &t0.F1.F2.F3, t0.F1.F2.F3,
)
}
输出:
0xc4200120d0 0xc4200120d0 42
0xc4200120f0 0xc4200120f0 0xc4200120f0 42
0xc420012100 0xc420012100 0xc420012100 0xc420012100 42
T0
type T0 struct{ F1 T1 }
type T1 struct{ F2 T2 }
type T2 struct{ F3 int }
相当于
type T0 struct {
F1 struct {
F2 struct {
F3 int
}
}
}
和T0
,F1
,F2
和F3
具有相同的地址。
在新示例中,T0
type T2 struct{ F3A, F3B int }
type T1 struct{ F2 T2 }
type T0 struct{ F1 T1 }
相当于
type T0 struct {
F1 struct {
F2 struct {
F3A int
F3B int
}
}
}
和T0
,F1
,F2
和F3A
具有相同的地址。 F3A
和F3B
有不同的地址。