为了账号安全,请及时绑定邮箱和手机立即绑定

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

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

Go
慕姐8265434 2021-11-29 15:40:30
我试图让 Go 接口工作,我遇到的问题是,只有在实现声明接口而不是实现接口的具体类型时,返回 go接口的 Go接口方法才有效。在以下示例中,我收到:prog.go:29: 不能在打印机参数中使用 &f (type *Bar) 作为 StringerGetter 类型:*Bar 没有实现 StringerGetter(GetStringer 方法的类型错误)有 GetStringer() *Foo 想要 GetStringer() fmt.Stringerpackage mainimport "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 方包中。我也希望能够编写自己的结构来实现上述接口,因此与具体返回类型进行接口也不是一种选择。我必须假设有一种方法可以做到这一点。
查看完整描述

3 回答

?
三国纷争

TA贡献1804条经验 获得超7个赞

您的问题是您试图使其他人(即另一个包的)类型符合它实际上不符合的接口。你不能那样做。但是你可以让你的类型符合你想要的任何东西。你可以让你的类型包装他们的类型。有两种方法可以做到这一点。这是一个:


type MyBar Bar


func (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可以互换,但他们很接近,它很容易将它们之间的转换,因为你需要。


查看完整回答
反对 回复 2021-11-29
?
一只甜甜圈

TA贡献1836条经验 获得超5个赞

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

“我想要”和 Go 不太匹配。

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

不,那里没有。接口完全匹配。Go 没有超类型或特化的概念。


查看完整回答
反对 回复 2021-11-29
?
慕丝7291255

TA贡献1859条经验 获得超6个赞

正如其他人所说,Go 不支持您尝试做的事情。

你有没有考虑过你的设计可能有点过于复杂了?

您通常不会像在其他语言(例如 Java)中那样在 Go 中找到工厂模式的工厂(例如)。

至少,这就是我假设您通过具有返回接口的接口来做的事情。

你总是可以制作一个新的包来保存工厂的工厂接口。

但通常,我会首先尝试查看该抽象级别是否值得您将在代码库中获得可读性。可能有更简单的方法来解决您的问题。


查看完整回答
反对 回复 2021-11-29
  • 3 回答
  • 0 关注
  • 165 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信