Home > Software design >  How to convert interface to another interface which it implements?
How to convert interface to another interface which it implements?

Time:01-31

In short - I would like to be able to cast an interface type whose underlying type implements a specific interface to that specific interface.

I am using the plugin package to lookup a New function which looks like so (I have many others the same):

func NewDomainPrimaryKey() any { return DomainPrimaryKey{} }

(This is generated at run-time so I can't just reference it as DomainPrimaryKey)

My lookup and call is like so:

                plugin, err := plugin.Open("my-plugin")
                if err != nil {
                    return err
                }

                symGet, err := plugin.Lookup("New"   pluginName)
                if err != nil {
                    return err
                }

                newGenModel, ok := symGet.(func() any)
                if !ok {
                    return errors.New("unexpected type from module symbol")
                }

                anyGenModel := newGenModel()
                genModel, ok := anyGenModel.(GenModel) // **this is where the problem is
                if !ok {
                    return errors.New("unexpected type from module symbol")
                }

                genModelInstance := genModel.Get()

In the above I am trying to cast 'anyGenModel' (an interface) to the 'GenModel' interface which it implements, however, this doesn't work.

I am certain it implements this interface because when I do the following, I get no errors.

type GenModel interface {
    Get() any
    TableName() string
}

var _ GenModel = (*DomainPrimaryKey)(nil) // this doesn't complain

How can I do this? I found this article which I don't think is what I am looking for but seems similar.

Thanks in advance for any help on this - this has become a real blocker for me.

CodePudding user response:

If the underlying type implements both interfaces, this is very straightforward:

package main

import "fmt"

type IFace1 interface {
    DoThis()
}

type IFace2 interface {
    DoThat()
}

type impl struct{}

func (i *impl) DoThis() {
    fmt.Println("I implement IFace1")
}

func (i *impl) DoThat() {
    fmt.Println("I implement IFace2")
}

func GetIFace1() IFace1 {
    return &impl{}
}

func main() {
    i1 := GetIFace1()

    i1.DoThis()

    i2 := i1.(IFace2)

    i2.DoThat()
}

playground

If your code is not working, then I would begin by questioning your assertion that the underlying type of anyGenModel actually implements GenModel and work from there.

  • Related