Adirio
Adirio

Reputation: 5286

How to check pointers after turning them into an interface

How can I compare pointers that were turned into interfaces?

package main

import (
    "fmt"
)

type ContainerInterface interface {
    Check(ContentInterface) bool
}

type ContentInterface interface {
    BelongsTo(ContainerInterface) bool
}

type BaseContainer struct {}

func (container *BaseContainer) Check(content ContentInterface) bool {
    return content.BelongsTo(container)
}

// The following are on a different package

type Container struct {
    BaseContainer
}

func (container *Container) GetContent() Content {
    return Content{container}
}

type Content struct {
    container *Container
}

func (content Content) BelongsTo(container ContainerInterface) bool {
    return container == content.container
}

func main() {
    container := &Container{}
    content := container.GetContent()
    fmt.Printf("%p\n%p\n%v\n", container, content.container, container == content.container)
    fmt.Println()
    fmt.Println(content.BelongsTo(container))
    fmt.Println(container.Check(content))
}

This returns:

0xXYZXYZ
0xXYZXYZ
true

true
false

0xXYZXYZ represents the same memory direction, but the last call is returning false when it should return true

Upvotes: 0

Views: 69

Answers (1)

GilesW
GilesW

Reputation: 515

This isn't a "pointers and interfaces" problem it is a "anonymous composition is not inheritance" problem. It's almost always a mistake to try to use go in an OOP kind of way.

When you call container.Check(content) , because type Container doesn't have a Check() method it gets delegated to the BaseContainer anonymous embbedded type's Check() method.

But methods on embedded structs don't have any visibility of the field of the parent struct or the parent struct itself - so you are actually checking (calling BelongsTo()) against the anonymous BaseContainer embedded struct not the outer container. This quite correctly returns false.

The fact that this is being done through an interface makes absolutely no difference to this.

If you really did want to code in this way you would have to put a field in the BaseContainer type that pointed to the outer container:

type BaseContainer struct {
  parent ContainerInterface
}

which would have to be initialised on creation of the parent struct and then the methods adapted to use this. (Although better just to avoid OO style altogether :) )

Upvotes: 2

Related Questions