如果结构具有参数实现接口的功能,则结构不实现接口

时间:2018-08-21 08:52:37

标签: go

我有一个包含两个接口的程序包

package main
type A interface {
    Close()
}
type B interface {
    Connect() (A, error)
}

我还有两个实现这些接口的结构

type C struct {
}

func (c *C) Close() {

}

type D struct {
}

func (d *D) Connect() (*C, error) {
    c := new(C)
    return c, nil
}

接下来我有一个函数,该函数需要一个实现接口B的对象作为参数

func test(b B) {
}

最后,在main()函数中,我创建了D结构对象,并想调用test()函数

func main() {
    d := new(D)
    test(d)
}

如果我尝试构建该软件包,则会出错。

  

不能在测试参数中使用d(* D型)作为B型:           * D没有实现B(Connect方法的类型错误)                   有Connect()(* C,错误)                   想要Connect()(A,错误)

这是我的代码的简单示例,其中我使用外部包并希望模拟结构进行测试。使用接口代替类型有什么解决方案吗?

2 个答案:

答案 0 :(得分:2)

您的Connect方法返回的类型应该是A而不是*C

您定义Connect方法的方式是它应该返回一个接口,而不是特定的类型。在实现*C接口的情况下,您仍然可以返回A

package main

type A interface {
    Close()
}

type B interface {
    Connect() (A, error)
}

type C struct {
}

func (c *C) Close() {
}

type D struct {
}

func (d *D) Connect() (A, error) {
    c := new(C)
    println("successfully created new C:", c)
    return c, nil
}

func test(b B) {
    b.Connect()
}

func main() {
    d := new(D)
    test(d)
}

输出

  

成功创建了新的C:0xe28f0

亲自尝试here

答案 1 :(得分:1)

要实现该接口,需要关注的是:

  

Go类型通过实现该接口的方法来满足该接口   界面,仅此而已。此属性允许定义接口   并且无需修改现有代码即可使用。它使一种   促进关注点分离和改善的结构化类型   代码的重用,并使其更容易建立在   代码得以发展。

您得到的错误是因为您用作测试函数的参数的结构D无法实现该接口。这背后的原因是您与接收方Connect一起使用的功能D是不同的。由于它具有不同的返回类型:

func (d *D) Connect() (*C, error) { // the struct D does not implement the interface B because of wrong function definition to interface B function
    c := new(C)
    return c, nil
}

如果要实现接口B,则函数定义及其返回类型应与接口B中的函数相匹配,

type B interface {
    Connect() (A, error)
}

因此,如果要实现接口,则使用的Connect方法应与接口B的Connect方法匹配。

package main

type A interface {
    Close()
}
type B interface {
    Connect() (A, error)
}

type C struct {
}

func (c *C) Close() {

}

type D struct {
}

func (d *D) Connect() (A, error) {
    c := new(C)
    return c, nil
}

func test(b B) {}

func main() {
    d := new(D)
    test(d)
}

检查Go Playground

考虑这个简单的界面,以表示可以与另一个值进行比较的对象:

type Equaler interface {
    Equal(Equaler) bool
}

和这种类型,T:

type T int
func (t T) Equal(u T) bool { return t == u } // does not satisfy Equaler

T.Equal的参数类型是T,而不是字面意义上必需的Equaler。

在Go中,类型系统不提升Equal参数;这是程序员的责任,如T2类型所示,它确实实现了Equaler:

type T2 int
func (t T2) Equal(u Equaler) bool { return t == u.(T2) }  // satisfies Equaler