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

Go Pointers: Slice of interfaces changing pointer address

每当我将附加结构的地址检索到实现接口的结构切片中时,它的指针地址似乎发生了变化。

游乐场: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)

    }
}

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

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

为了回答我的问题,我能否以某种方式更改我的切片或结构以解决此问题并希望不要沿着反射路线进行。 "get around" 我的意思是通过切片获取原始地址。

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

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

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

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

题中的代码打印了局部变量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} 而不是指针值。

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