-
前言
在Go语言的语境中,我们在谈论接口时,一定指的是接口类型。因为接口类型与其他数据类型不同,我们既不能通过调用new函数或make函数创建出一个接口类型的值,也无法用字面量来表示一个接口类型的值。
对于某一个接口类型来说,如果没有任何数据类型可以作为它的实现,那么该接口的值就不可能存在
-
定义
通过关键字type和interface我们可以声明出接口类型,{}下包裹的是它的方法定义。如下例
type Pet interface {
SetName(name string)
Name() string
Category() string
}
-
实现
对于任何的数据类型,只要它的方法集合中完全包含了一个接口的全部方法,那么他就是这个接口的实现类型。无需显式地声明
type Dog struct {
name string // 名字。
}
func (dog *Dog) SetName(name string) {
dog.name = name
}
func (dog Dog) Name() string {
return dog.name
}
func (dog Dog) Category() string {
return "dog"
}
这时我们可以说Dog类型是pet接口的实现类型
-
赋值
注意事项
(1) 类型T的对象赋值给接口变量时,要求类型T的所有方法的接收器类型必须是T
(2) 类型*T的对象赋值给接口变量时,类型T的方法接收器类型可以是T或者*T
(3) 在golang中,只要两个接口具有相同的方法列表,那么他们就是等同的,就可以相互赋值;如果一个接口的方法列表包含了另一个接口的方法列表,那么可以将大的接口变量赋值给小的接口变量
-
接口组合
与结构体类型间的嵌入很相似,我们只要把一个接口类型的名称直接写到另一个接口类型的成员列表中就可以了
接口类型的嵌入更要简单一些,它不会涉及方法间的屏蔽。只要组合的接口之间有同名的方法就会产生冲突,从而无法通过编译,即使同名方法的签名彼此不同也会是如此
type Animal interface {
ScientificName() string
Category() string
}
type Pet interface {
Animal
Name() string
}
此时,animal接口包含的所有方法也就成为了pet的接口方法
善用接口组合和小接口可以让程序框架更加稳定和灵活