结构是否实现了其嵌入类型之一实现的所有接口?

时间:2015-08-10 15:20:37

标签: struct go

我有这个例子

// embed project main.go
package main

import (
    "fmt"
)

type A struct {
    A1 int
    A2 int
}

func (a A) Incr() int {
    a.A1++
    return a.A1
}

type B struct {
    A
    D int
}

type C interface {
    Incr() int
}

func Add(c C) {
    d := c.Incr()
    fmt.Println(d)
}

func main() {
    var s B
    s.Incr() //B has Incr
    Add(s)
}

使用这个例子我想检查B是否实现了接口C.在此示例中,添加接受s(类型B)作为输入。 B实施C

但是当我将Incr()方法从原始改为

func (a *A) Incr() int {
    a.A1++
    return a.A1
}

它编译器给出了错误

  

./ main.go:35:不能在参数中使用s(类型B)作为类型C.   AddContent:B没有实现C(Incr方法有指针接收器)

所以我仍然困惑一个结构是否实现了其嵌入式类型之一的所有接口。

2 个答案:

答案 0 :(得分:2)

  

如果S包含匿名字段T,则S和* S的方法集都包括带有接收方T的提升方法。* S的方法集还包括带接收方* T的提升方法。

     

如果S包含匿名字段* T,则S和* S的方法集都包含   用接收者T或* T推广方法。

B嵌入A,因此B的方法集包括带接收器A的启动方法,但不包括* A

答案 1 :(得分:2)

是的,你的struct实现了嵌入式的方法集。

但是,当您将Incr的签名更改为func (a *A) Incr() int时,您需要一个指针用于该方法的接收者。 <{1}}本身在有指针接收器时不会实现A

Incr调用的作用原因是s.Incr()值是可寻址的,并且Go会自动引用它以进行方法调用。当您将s传递给s时,您尝试将其转换为Add界面,该值将不再可寻址,并且C方法不会在方法集中。

在这种情况下,您可以将嵌入类型更改为Incr

*A

在呼叫站点获取type B struct { *A D int } 的地址

s

或使Add(&s) 指针(s):

*B

relevent portion of the spec

  

给定结构类型S和名为T的类型,提升的方法是   包含在结构的方法集中,如下所示:

     
      
  • 如果S包含匿名字段T,则S和* S的方法集都包括带有接收者T的提升方法。* S的方法集也   包括带接收器* T的推广方法。
  •   
  • 如果S包含匿名字段* T,则S和* S的方法集都包括带有接收者T或* T的提升方法。
  •