1
votes

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.

2
Kinda gotta ask why you care at all about the addresses of things. What is your actual concern? - captncraig
I'm running into a few other bugs and while testing the pointer addresses i noticed this. - FanManPro
Line 8 is unnecessary, does nothing useful i.e. can be deleted, and its presence may confuse the issue. - Doug Henderson

2 Answers

2
votes

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

Run it on the playground.

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.

-1
votes

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.