猿问

Go接口方法返回接口与返回具体类型的方法不匹配

我试图让 Go 接口工作,我遇到的问题是,只有在实现声明接口而不是实现接口的具体类型时,返回 go接口的 Go接口方法才有效。


在以下示例中,我收到:


prog.go:29: 不能在打印机参数中使用 &f (type *Bar) 作为 StringerGetter 类型:*Bar 没有实现 StringerGetter(GetStringer 方法的类型错误)有 GetStringer() *Foo 想要 GetStringer() fmt.Stringer


package main


import "fmt"


type Foo struct {

    val string

}


func (f *Foo) String() string {

    return f.val

}


type StringerGetter interface {

    GetStringer() fmt.Stringer

}


type Bar struct{}


func (b *Bar) GetStringer() *Foo {

    return &Foo{"foo"}

}


func Printer(s StringerGetter) {

    fmt.Println(s.GetStringer())

}


func main() {

    f := Bar{}

    Printer(&f)

}

但是,如果我更改func (b *Bar) GetStringer() *Foo {为func (b *Bar) GetStringer() fmt.Stringer {它会按预期工作。


Foo 确实满足 fmt.Stringer


问题在于上面是说明问题的简单示例代码。


在我尝试编写的代码的情况下,我创建的接口在我的"main"包中,而我正在编写接口的具体类型在我不想修改的第 3 方包中。


我也希望能够编写自己的结构来实现上述接口,因此与具体返回类型进行接口也不是一种选择。


我必须假设有一种方法可以做到这一点。


慕姐8265434
浏览 166回答 3
3回答

三国纷争

您的问题是您试图使其他人(即另一个包的)类型符合它实际上不符合的接口。你不能那样做。但是你可以让你的类型符合你想要的任何东西。你可以让你的类型包装他们的类型。有两种方法可以做到这一点。这是一个:type MyBar Barfunc (b *MyBar) GetStringer() fmt.Stringer {    return &Foo{"foo"}}func main() {    f := MyBar(Bar{})    Printer(&f)}现在我们已经创建了一个新类型,MyBar它包装了 aBar并提供了你想要的接口。但是,这种方法不会从 中“继承”任何其他功能Bar。你必须包装你想要的每一个单独的东西,你可能不得不重新实现(因为你无权访问底层的实现)。但是您也可以嵌入Bar和“继承”您不会更改的所有内容并访问底层 impl(这可能更接近您在此处想要的内容)。例如:type MyBar struct{ Bar }func (b *MyBar) GetStringer() fmt.Stringer {    return b.Bar.GetStringer()}func main() {    f := MyBar{Bar{}}    Printer(&f)}现在,如果Bar有其他方法,它们将MyBar免费显示。根据您的问题,两者都可能有用。您可以使用此技术来帮助其他包类型符合您的要求。这并不意味着,Bar和MyBar可以互换,但他们很接近,它很容易将它们之间的转换,因为你需要。

一只甜甜圈

我也希望能够编写自己的结构来实现上述接口,因此与具体返回类型进行接口也不是一种选择。“我想要”和 Go 不太匹配。我必须假设有一种方法可以做到这一点。不,那里没有。接口完全匹配。Go 没有超类型或特化的概念。

慕丝7291255

正如其他人所说,Go 不支持您尝试做的事情。你有没有考虑过你的设计可能有点过于复杂了?您通常不会像在其他语言(例如 Java)中那样在 Go 中找到工厂模式的工厂(例如)。至少,这就是我假设您通过具有返回接口的接口来做的事情。你总是可以制作一个新的包来保存工厂的工厂接口。但通常,我会首先尝试查看该抽象级别是否值得您将在代码库中获得可读性。可能有更简单的方法来解决您的问题。
随时随地看视频慕课网APP

相关分类

Go
我要回答