接口
是一种类型
在Go
语言中接口(interface
)是一种类型,一种抽象的类型。它规定了变量有哪些方法
interface
是一组method
的集合,是duck-type programming
的一种体现。接口做的事情就像是定义一个协议(规则),只要一台机器有洗衣服和甩干的功能,我就称它为洗衣机。不关心属性(数据),只关心行为(方法)。
在编程中会遇到以下场景:
:::warning 我不关心一个变量是什么类型,我只关心能调用它的什么方法。
:::
接口的定义
type 接口名 interface {
方法名1(参数1, 参数2...)(返回值1,返回值2,...)
方法名2(参数1, 参数2...)(返回值1,返回值2,...)
...
}
用来给变量、参数、返回值等设置类型。
实战
type speak interface {
Say() string
}
type Cat struct{}
func (c Cat) Say() string { return "喵喵喵" }
type Dog struct{}
func (d Dog) Say() string { return "汪汪汪" }
func main() {
c := Cat{}
fmt.Println("猫:", c.Say())
d := Dog{}
fmt.Println("狗:", d.Say())
}
type Cat struct{}
func (c Cat) Say() string { return "喵喵喵" }
type Dog struct{}
func (d Dog) Say() string { return "汪汪汪" }
func main() {
c := Cat{}
fmt.Println("猫:", c.Say())
d := Dog{}
fmt.Println("狗:", d.Say())
}
接口的实现
:::info 一个变量如果实现了接口中规定的所有方法,那么这个变量就实现了这个接口,可以称为这个接口类型的变量。
:::
使用值接收者实现接口与使用指针接收者实现接口的区别?
使用值接收者实现接口,结构体类型和结构体指针类型的变量都能保存。
- 因为Go语言中有对指针类型变量求值的语法糖,指针内部(如
<font style="color:rgb(68, 68, 68);">&cat</font>
)会自动求值<font style="color:rgb(68, 68, 68);background-color:rgb(248, 248, 248);">*cat</font>
。
指针接收者实现接口,只能存结构体指针类型的变量
- 变量只能存储指针类型的值
实现了接口有什么用呢?
接口类型变量能够存储所有实现了该接口的实例。 例如上面的示例中,Sayer
类型的变量能够存储dog
和cat
类型的变量。
这里其实能感觉出来和java里面接口的相似之处了。 类型看左边,实现看右边
func main() {
var x Sayer // 声明一个Sayer类型的变量x
a := cat{} // 实例化一个cat
b := dog{} // 实例化一个dog
x = a // 可以把cat实例直接赋值给x
x.say() // 喵喵喵
x = b // 可以把dog实例直接赋值给x
x.say() // 汪汪汪
}
Tips: 观察下面的代码,体味此处_
的妙用
// 摘自gin框架routergroup.go
type IRouter interface{ ... }
type RouterGroup struct { ... }
var _ IRouter = &RouterGroup{} // 确保RouterGroup实现了接口IRouter