go语言的接口,是一种新的类型定义,它把所有的具有共性的方法定义在一起,任何其他类型只要实现了这些方法就是实现了这个接口。
/* 定义接口 */
type interface_name interface {
method_name1 [return_type]
method_name2 [return_type]
method_name3 [return_type]
...
method_namen [return_type]
}
/* 定义结构体 */
type struct_name struct {
/* variables */
}
/* 实现接口方法 */
func (struct_name_variable struct_name) method_name1() [return_type] {
/* 方法实现 */
}
...
func (struct_name_variable struct_name) method_namen() [return_type] {
/* 方法实现*/
}
下面我定义一个USB接口,有读read和写write两个方法,再定义一个电脑Computer和一个手机Mobile来实现这个接口。
USB接口
type USB interface {
read()
write()
}
Computer结构体
type Computer struct {
}
Mobile结构体
type Mobile struct {
}
Computer实现USB接口方法
func (c Computer) read() {
fmt.Println("computer read...")
}
func (c Computer) write() {
fmt.Println("computer write...")
}
Mobile实现USB接口方法
func (c Mobile) read() {
fmt.Println("mobile read...")
}
func (c Mobile) write() {
fmt.Println("mobile write...")
}
测试
func main() {
c := Computer{}
m := Mobile{}
c.read()
c.write()
m.read()
m.write()
}
运行结果
func main() {
c := Computer{}
m := Mobile{}
c.read()
c.write()
m.read()
m.write()
}
下面我们定义一个OpenClose接口,里面有两个方法open和close,定义个Door结构体,实现其中一个方法。
package main
import "fmt"
type OpenClose interface {
open()
close()
}
type Door struct {
}
func (d Door) open() {
fmt.Println("open door...")
}
func main() {
var oc OpenClose
oc = Door{} // 这里编译错误,提示只实现了一个接口
}
这个话题,本质上和方法的值类型接收者和指针类型接收者,的思考方法是一样的,值接收者是一个拷贝,是一个副本,而指针接收者,传递的是指针。
举例
定义一个Pet接口
type Pet interface {
eat()
}
定义一个Dog结构体
type Dog struct {
name string
}
实现Pet接口(接收者是值类型)
func (dog Dog) eat() {
fmt.Printf("dog: %p\n", &dog)
fmt.Println("dog eat..")
dog.name = "黑黑"
}
测试
func main() {
dog := Dog{name: "花花"}
fmt.Printf("dog: %p\n", &dog)
dog.eat()
fmt.Printf("dog: %v\n", dog)
}
运行结果
dog: 0xc000046240
dog: 0xc000046250
dog eat..
dog: {花花}
从运行结果,我们看出dog的地址变了,说明是复制了一份,dog的name没有变说明,外面的dog变量没有被改变。
将Pet接口改为指针接收者
func (dog *Dog) eat() {
fmt.Printf("dog: %p\n", dog)
fmt.Println("dog eat..")
dog.name = "黑黑"
}
再测试
func main() {
dog := &Dog{name: "花花"}
fmt.Printf("dog: %p\n", dog)
dog.eat()
fmt.Printf("dog: %v\n", dog)
}
运行结果
dog: 0xc00008c230
dog: 0xc00008c230
dog eat..
dog: &{黑黑}
一个类型实现多个接口,例如:有一个Player接口可以播放音乐,有一个Video接口可以播放视频,一个手机Mobile实现这两个接口,既可以播放音乐,又可以播放视频。
定义一个Player接口
type Player interface {
playMusic()
}
定义一个Video接口
type Video interface {
playVideo()
}
定义Mobile结构体
type Mobile struct {
}
实现两个接口
func (m Mobile) playMusic() {
fmt.Println("播放音乐")
}
func (m Mobile) playVideo() {
fmt.Println("播放视频")
}
测试
func main() {
m := Mobile{}
m.playMusic()
m.playVideo()
}
运行结果
播放音乐
播放视频
比如,一个宠物接口Pet,猫类型Cat和狗类型Dog都可以实现该接口,都可以把猫和狗当宠物类型对待,这在其他语言中叫做多态。
定义一个Pet接口
type Pet interface {
eat()
}
定义一个Dog结构体
type Dog struct {
}
定义一个Cat结构体
type Cat struct {
}
实现接口
func (cat Cat) eat() {
fmt.Println("cat eat...")
}
func (dog Dog) eat() {
fmt.Println("dog eat...")
}
测试
func main() {
var p Pet
p = Cat{}
p.eat()
p = Dog{}
p.eat()
}
运行结果
cat eat...
dog eat...
接口可以通过嵌套,创建新的接口。例如:飞鱼,既可以飞,又可以游泳。我们创建一个飞Fly接口,创建一个游泳接口Swim,飞鱼接口有这两个接口组成。
飞Flyer接口
type Flyer interface {
fly()
}
创建Swimmer接口
type Swimmer interface {
swim()
}
组合一个接口FlyFish
type FlyFish interface {
Flyer
Swimmer
}
创建一个结构体Fish
type Fish struct {
}
实现这个组合接口
func (fish Fish) fly() {
fmt.Println("fly...")
}
func (fish Fish) swim() {
fmt.Println("swim...")
}
测试
func main() {
var ff FlyFish
ff = Fish{}
ff.fly()
ff.swim()
}
运行结果
fly...
swim...