Golang中的隐式接口转换

3
这是我想要展示的一个例子。
package main
import "fmt"

// interface declaration
//

type A interface {
    AAA() string
}

type B interface{
    Get() A
}

// implementation
//

type CA struct {}

// implementation of A.AAA
func (ca *CA) AAA() string {
    return "it's CA"
}

type C struct {}

// implementation of B.Get, except for returning a 'struct' instead of an 'interface'
func (c *C) Get() *CA {
    return &CA{}
}

func main() {
    var c interface{} = &C{}
    d := c.(B)
    fmt.Println(d.Get().AAA())
    fmt.Println("Hello, playground")
}

在这个例子中:
  • 接口 B 有一个方法 Get,用于返回一个接口 A
  • 结构体 C 有一个成员函数 Get,用于返回指向实现接口 A 的结构体 CA 的指针
结果是 Go 不能从结构体 C 推断出接口 B,即使它们的 Get 方法只有返回类型不同,但可转换。
我提出这个问题的原因是当接口 A、B结构体 C、CA位于不同的包中时,我只能做以下两种选择:
  • C 的 Get 方法精化为 func Get() A,这会在包之间引入一些依赖关系。
  • 将接口 B 和结构体 C 的 Get 方法都精化为 func Get() interface{}
我想避免包之间的依赖关系,并尽量不依赖于 interface{},有人可以给我一些提示吗?在Go中的最佳实践是什么?
1个回答

3

您目前使用的*C类型未实现B接口,因此不能将*C类型的值分配给B类型的变量,也不能从保存*C类型值的对象中进行“类型断言”来获取B类型的值。

以下是您可以采取的措施。由于您已经在使用结构体字面值(&C{}),您可以声明c*C类型,并调用其Get()方法,再将C.Get()的返回值转换为A类型(因为返回值实现了A接口):

var c *C = &C{}
var a A = c.Get() // This is ok, implicit interface value creation (of type A)
fmt.Println(a.AAA())
// Or without the intermediate "a", you can simply call:
fmt.Println(c.Get().AAA())

输出:

it's CA
it's CA

重构:

问题在于你有一个要实现的接口(B),它有一个方法返回另一个接口(A)。要实现这个B接口,你必须依赖于定义A的包,这是无法避免的。同时,你必须声明C.Get()返回A(而不是一个具体的结构类型)。

你可以将A移到第三个包中,然后定义C的包只需依赖于这第三个包,而不是定义B的包(但仍将隐式实现接口类型B)。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接