如何将一个实现了某个接口的接口转换为另一个接口?

huangapple go评论126阅读模式
英文:

How to convert interface to another interface which it implements?

问题

简而言之,我想要能够将底层类型实现了特定接口的接口类型转换为该特定接口。

我正在使用plugin包来查找一个New函数,它的样子如下(我有很多其他相同的函数):

func NewDomainPrimaryKey() any { return DomainPrimaryKey{} }

(这是在运行时生成的,所以我不能直接引用它作为DomainPrimaryKey)

我的查找和调用代码如下:

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) // **这里出现了问题
if !ok {
    return errors.New("unexpected type from module symbol")
}

genModelInstance := genModel.Get()

在上面的代码中,我试图将anyGenModel(一个接口)转换为它实现的GenModel接口,但是这样做不起作用。

我确定它实现了这个接口,因为当我执行以下操作时,没有出现错误。

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

var _ GenModel = (*DomainPrimaryKey)(nil) // 这没有报错

我该如何做呢?我找到了这篇文章,但我不认为它是我要找的,尽管看起来有些相似。

提前感谢您对此的任何帮助 - 这对我来说已经成为一个真正的障碍。

英文:

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.

答案1

得分: 0

如果底层类型实现了这两个接口,那么这非常简单:

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

如果你的代码不起作用,那么我会首先质疑你对anyGenModel的底层类型是否真的实现了GenModel接口,然后从那里开始排查。

英文:

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.

huangapple
  • 本文由 发表于 2023年1月27日 22:53:56
  • 转载请务必保留本文链接:https://go.coder-hub.com/75259767.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定