首页 文章

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")
}

在这个例子中

  • interface B 有一个方法 Get 返回一个接口 A

  • struct C 有一个成员函数 Get ,用于返回指向struct CA 的指针,该指针实现了接口 A

结果是Go无法从struct C 中推断出界面 B ,即使它们的 Get 方法仅在返回类型中是不同的,这是可转换的 .

我提出这个问题的原因是当 interface A, Bstruct C, CA 在不同的包中时,我只能:

  • C 的Get方法细化为 func Get() A ,这会在包之间引入一些依赖关系 .

  • Get 接口 Get 和struct C 的方法细化为 func Get() interface{}

我想避免包之间的依赖,尽量不要依赖 interface{} ,任何人都可以给我一些提示吗? Go的最佳做法是什么?

1 回答

  • 3

    您当前的 *C 类型 does not 实现了接口 B ,因此您不能将 *C 的值分配给 B 类型的变量,也不能将 B 的值分配给 B 的值 B .

    这里's what you can do. Since you'已经使用了结构文字( &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
    

    Or refactor:

    问题是你有一个你想要实现的接口( B ),它有一个返回另一个接口的方法( A ) . 要实现此 B 接口,您必须依赖于定义 A 的包,您无法避免这种情况 . 并且您必须声明 C.Get() 以返回 A (而不是具体的结构类型) .

    您可以将 A 移动到第3个包,然后定义 C 的包只需依赖于此第3个包,但不依赖于定义 B 的包(但仍将隐式实现接口类型 B ) .

相关问题