Pointers Go指针:改变指针地址的接口片

Pointers Go指针:改变指针地址的接口片,pointers,go,interface,slice,memory-address,Pointers,Go,Interface,Slice,Memory Address,每当我将附加结构的地址检索到实现接口的结构片中时,它的指针地址似乎会改变 游乐场: 正如在结果中打印出来时所看到的,结构的地址确实发生了变化,但值保持不变 我在网上了解到,当一个结构实现一个接口时,会有一些额外的内存数据存储在该结构中。(我假设这就是改变我地址的原因) 为了回答我的问题,我是否可以通过某种方式更改切片或结构来绕过这个问题,希望不要走上反射路线。我所说的“四处走动”是指通过切片获取原始地址。在你的代码中,红苹果和杂货店。Rotters[0]不是一回事。一个是指向苹果的直接指针,另一

每当我将附加结构的地址检索到实现接口的结构片中时,它的指针地址似乎会改变

游乐场:

正如在结果中打印出来时所看到的,结构的地址确实发生了变化,但值保持不变

我在网上了解到,当一个结构实现一个接口时,会有一些额外的内存数据存储在该结构中。(我假设这就是改变我地址的原因)


为了回答我的问题,我是否可以通过某种方式更改切片或结构来绕过这个问题,希望不要走上反射路线。我所说的“四处走动”是指通过切片获取原始地址。

在你的代码中,
红苹果和
杂货店。Rotters[0]
不是一回事。一个是指向苹果的直接指针,另一个是
Rotter
接口值

接口类型的变量本身是指向结构的指针,该结构是类型信息和基础值(本例中为实际指针)的组合

因此,第二次打印是将地址提供给接口值,而不是底层实现的值


有一些关于如何存储接口值的更好的细节。

问题中的代码打印局部变量的地址
red\u apple
fruit
。它们是不同的变量,因此具有不同的地址

添加到切片的指针值与从切片检索到的接口中的值相同。试试这个:

red_apple := &Apple{Color: "Red"}

fmt.Println(red_apple.GetColor())
fmt.Printf("%p\n", red_apple) // print the value in red_apple as a pointer

grocer := &Shop{}
grocer.Rotters = append(grocer.Rotters, red_apple)

for _, fruit := range grocer.Rotters {
    fmt.Println(fruit.GetColor())
    fmt.Printf("%p\n", fruit)  // print the value in fruit as a pointer
    fmt.Println(fruit == red_apple) 
}

请注意,这不是打印问题。我在这里使用
%p
格式,因为
fmt.Println(红色苹果)
fmt.Println(水果)
print
&{red}
的输出代替了指针值


关键的一点是,您应该打印添加到切片和从切片中检索到的值,而不是本地变量的地址。

%p
的作用是什么?%p以16进制表示法格式化指针值,前导为0x。我使用了%p,因为该值的默认格式不显示地址。啊。关键在fmt文档中:
不管动词是什么,如果操作数是接口值,则使用内部具体值,而不是接口本身。
因此它们仍然不是相同的东西,但打印它们的方式使您进入相同的内部东西。不知道为什么重要,但有一个区别。不,对于语言来说,它们是有两个不同地址的东西。fmt包认识到接口值包含一个指向具体值的指针,并向您展示了这一点。有点想问一下,为什么您关心事物的地址。您真正关心的是什么?我遇到了一些其他错误,在测试指针地址时,我注意到了这一点。第8行是不必要的,没有任何有用的功能,即可以删除,它的存在可能会混淆问题。
red_apple := &Apple{Color: "Red"}

fmt.Println(red_apple.GetColor())
fmt.Printf("%p\n", red_apple) // print the value in red_apple as a pointer

grocer := &Shop{}
grocer.Rotters = append(grocer.Rotters, red_apple)

for _, fruit := range grocer.Rotters {
    fmt.Println(fruit.GetColor())
    fmt.Printf("%p\n", fruit)  // print the value in fruit as a pointer
    fmt.Println(fruit == red_apple) 
}