语言规范里只有这两条规则,我通过这两条规则得出了符合我们例子的规则:
1.类型 T 的可调用方法集不包含接受者为 *T 的方法
我们碰巧赶上了我推断出的这条规则,所以编译器会报错。Notify 方法使用指针类型作为接受者而我们却通过值类型来调用该方法。解决办法也很简单,我们只需要传入 User 值的地址到 SendNotification 函数就好了:
func main() {
user := &User{
Name: "AriesDevil",
Email: "ariesdevil@xxoo.com",
}
SendNotification(user)
}
// Output:
User: Sending User Email To AriesDevil<ariesdevil@xxoo.com>
详细代码:http://play.golang.org/p/kEKzyTfLjA
嵌入类型
结构体类型可以包含匿名或者嵌入字段。也叫做嵌入一个类型。当我们嵌入一个类型到结构体中时,该类型的名字充当了嵌入字段的字段名。
下面定义一个新的类型然后把我们的 User 类型嵌入进去:
type Admin struct {
User
Level string
}
我们定义了一个新类型 Admin 然后把 User 类型嵌入进去,注意这个不叫继承而叫组合。 User 类型跟 Admin 类型没有关系。
我们来改变一下 main 函数,创建一个 Admin 类型的变量并把变量的地址传入 SendNotification 函数中:
func main() {
admin := &Admin{
User: User{
Name: "AriesDevil",
Email: "ariesdevil@xxoo.com",
},
Level: "master",
}
SendNotification(admin)
}
// Output
User: Sending User Email To AriesDevil<ariesdevil@xxoo.com>
详细代码:http://play.golang.org/p/ivzzzk78TC
事实证明,我们可以 Admin 类型的一个指针来调用 SendNotification 函数。现在 Admin 类型也通过来自嵌入的 User 类型的方法提升实现了该接口。
如果 Admin 类型包含了 User 类型的字段和方法,那么它们在结构体中的关系是怎么样的呢?
当我们嵌入一个类型,这个类型的方法就变成了外部类型的方法,但是当它被调用时,方法的接受者是内部类型(嵌入类型),而非外部类型。— Effective Go
因此嵌入类型的名字充当着字段名,同时嵌入类型作为内部类型存在,我们可以使用下面的调用方法:
admin.User.Notify()
// Output
User: Sending User Email To AriesDevil<ariesdevil@xxoo.com>
详细代码:http://play.golang.org/p/0WL_5Q6mao
这儿我们通过类型名称来访问内部类型的字段和方法。然而,这些字段和方法也同样被提升到了外部类型:










