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

时间:2017-05-04 23:09:22

标签: pointers go interface slice memory-address

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

游乐场:https://play.golang.org/p/MmAS6S5IqH

pod install

正如在结果中打印出来的那样,结构的地址确实会改变,但值保持不变。

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

为了解决我的问题,我可以以某种方式改变我的切片或结构以解决这个问题,并希望不会沿着反射路线走下去。通过"绕过"我的意思是通过切片获取原始地址。

2 个答案:

答案 0 :(得分:2)

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

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

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) 
}

Run it on the playground.

请注意,这不是打印问题。我在这里使用%p格式,因为fmt.Println(red_apple)fmt.Println(fruit)的输出打印&{<nil> Red}而不是指针值。

关键是你应该打印添加到切片中并从切片中检索的值,而不是局部变量的地址。

答案 1 :(得分:-1)

在您的代码中,red_applegrocer.Rotters[0]不是一回事。一个是指向Apple的直接指针,另一个是Rotter接口值。

接口类型的变量本身是指向结构的指针,该结构是类型信息和基础值(在这种情况下为真实指针)的组合。

所以你的第二次打印是给出接口值的地址,而不是底层实现的值。

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