匿名/明确地在struct中嵌入接口

问题描述

type A interface {
    f()
}

type B struct {
    A
}

type C struct {
    Imp A
}

func main() {
    b := B{}
    c := C{}
    //b can be directly assigned to the A interface,but c prompts that it cannot be assigned
    var ab A = b
    //Cannot use 'c' (type C) as type A in assignment Type does not implement 'A' as some methods are missing: f() 
    var ac A = c
}

B结构和C结构之间有什么区别?

在Go表中

使用类型声明但没有显式字段名称的字段称为嵌入字段。必须将嵌入字段指定为类型名称T或指向非接口类型名称* T的指针,并且T本身可能不是指针类型。非限定类型名称用作字段名称。

解决方法

如果您继续阅读相同的规范section of the spec,则会注意到以下内容:

给定一个结构类型S和一个定义的类型T,提升的方法是 包含在该结构的方法集中的方法如下:

  • 如果S包含嵌入字段T,则S和* S的方法集 包括接收方T的提升方法。* S的方法集 包括接收方* T的改进方法。
  • 如果S包含嵌入式 字段* T,S和* S的方法集都包含升级方法 接收者为T或* T。

您的结构B上没有明确定义方法,但是 B的方法集隐含地包括来自嵌入式字段的提升方法。在这种情况下,嵌入式字段是与方法f()的接口。您可以使用任何满足该接口要求的对象,并且其f()方法将自动成为为B设置的方法的一部分。

另一方面,您的C结构具有一个命名字段。 Imp上的方法不会自动添加到C的方法集中。相反,要从f()访问Imp方法,您需要专门调用C.Imp.f()

最后:使用接口作为(嵌入或不嵌入)字段的事实并不重要,它很可能是具有f()方法的另一个结构。 重要的部分是f()是否成为父结构的方法集的一部分,这将使其能够实现A

相关问答

依赖报错 idea导入项目后依赖报错,解决方案:https://blog....
错误1:代码生成器依赖和mybatis依赖冲突 启动项目时报错如下...
错误1:gradle项目控制台输出为乱码 # 解决方案:https://bl...
错误还原:在查询的过程中,传入的workType为0时,该条件不起...
报错如下,gcc版本太低 ^ server.c:5346:31: 错误:‘struct...