Anonymous/explicitly 在结构中嵌入了一个接口

Anonymous/explicitly embedded a interface in 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 结构有什么不同?

围棋sheet

A field declared with a type but no explicit field name is called an embedded field. An embedded field must be specified as a type name T or as a pointer to a non-interface type name *T, and T itself may not be a pointer type. The unqualified type name acts as the field name.

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

Given a struct type S and a defined type T, promoted methods are included in the method set of the struct as follows:

  • If S contains an embedded field T, the method sets of S and *S both include promoted methods with receiver T. The method set of *S also includes promoted methods with receiver *T.
  • If S contains an embedded field *T, the method sets of S and *S both include promoted methods with receiver T or *T.

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

方法集的一部分

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

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