英文:
Go Pointers: Slice of interfaces changing pointer address
问题
每当我将附加的结构体的地址检索到实现接口的结构体切片中时,其指针地址似乎会发生变化。
Playground: https://play.golang.org/p/MmAS6S5IqH
package main
import (
"fmt"
)
type Apple struct {
Rotter
Color string
}
func (a *Apple) GetColor() string {
return a.Color
}
type Shop struct {
Rotters []Rotter
}
type Rotter interface {
GetColor() string
}
func main() {
red_apple := &Apple{Color: "Red"}
fmt.Println(red_apple.GetColor())
fmt.Println(&red_apple)
grocer := &Shop{}
grocer.Rotters = append(grocer.Rotters, red_apple)
for _, fruit := range grocer.Rotters {
fmt.Println(fruit.GetColor())
fmt.Println(&fruit)
}
}
从打印结果中可以看出,结构体的地址确实发生了变化,但值保持不变。
根据我在网上的了解,当一个结构体实现一个接口时,结构体中会存储一些额外的内存数据。(我猜这就是导致地址变化的原因)
针对我的问题,我是否可以通过更改切片或结构体来解决这个问题,而不必使用反射。通过“解决”我指的是通过切片获取原始地址。
英文:
Whenever I retrieve the address of an appended struct into an slice of structs that implements an interface, its pointer address seems to change.
Playground: https://play.golang.org/p/MmAS6S5IqH
package main
import (
"fmt"
)
type Apple struct {
Rotter
Color string
}
func (a *Apple) GetColor() string {
return a.Color
}
type Shop struct {
Rotters []Rotter
}
type Rotter interface {
GetColor() string
}
func main() {
red_apple := &Apple{Color: "Red"}
fmt.Println(red_apple.GetColor())
fmt.Println(&red_apple)
grocer := &Shop{}
grocer.Rotters = append(grocer.Rotters, red_apple)
for _, fruit := range grocer.Rotters {
fmt.Println(fruit.GetColor())
fmt.Println(&fruit)
}
}
As seen when printed out in the results, the addresses of the structs does change however the values stay the same.
From what I've understand online is that when a struct implements a interface, there is some additional memory data stored with the struct. (I'm assuming this is whats changing my address)
To get to my question, can I somehow change my slice or struct in order to get around this issue and hopefully not go down the reflection route. By "get around" I mean get the original address via the slice.
答案1
得分: 2
问题中的代码打印了局部变量red_apple
和fruit
的地址。它们是不同的变量,因此具有不同的地址。
将指针值添加到切片中的操作与从切片中检索的接口值相同。尝试以下代码:
red_apple := &Apple{Color: "Red"}
fmt.Println(red_apple.GetColor())
fmt.Printf("%p\n", red_apple) // 打印red_apple的指针值
grocer := &Shop{}
grocer.Rotters = append(grocer.Rotters, red_apple)
for _, fruit := range grocer.Rotters {
fmt.Println(fruit.GetColor())
fmt.Printf("%p\n", fruit) // 打印fruit的指针值
fmt.Println(fruit == red_apple)
}
请注意,这不是一个打印问题。我在这里使用%p
格式,因为fmt.Println(red_apple)
和fmt.Println(fruit)
的输出打印的是&{<nil> Red}
而不是指针值。
关键点是应该打印添加到切片中和从切片中检索的值,而不是局部变量的地址。
英文:
The code in the question prints the addresses of local variables red_apple
and fruit
. They are different variables and therefore have different addresses.
The pointer value added to the slice is the same as the value in the interface retrieved from the slice. Try this:
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)
}
Note that this is not a printing issue. I use the %p
format here because the output for fmt.Println(red_apple)
and fmt.Println(fruit)
print &{<nil> Red}
instead of the pointer value.
The key point is that you should print the value added to and retrieved from the slice, not the address of the local variables.
答案2
得分: -1
在你的代码中,red_apple
和grocer.Rotters[0]
不是同一件事。一个是指向Apple的直接指针,另一个是Rotter
接口值。
接口类型的变量本身是指向一个结构体的指针,该结构体是类型信息和底层值(在这种情况下是真正的指针)的组合。
因此,你的第二个打印输出的是接口值的地址,而不是底层实现的值。
这个问题提供了一些关于接口值存储方式的更详细信息。
英文:
In your code, red_apple
and grocer.Rotters[0]
are not the same thing. One is a direct pointer to an Apple, and the other is a Rotter
interface value.
A variable of an interface type is itself a pointer to a structure that is a combination of type information, and the underlying value (the real pointer in this case).
So your second printing is giving the address to the interface value, not the underlying implementation's value.
This question has some better details on how interface values are stored.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论