Go语言学习之旅--接口

接口

  • 接口
  • 实现接口必须实现接口中的所有方法
  • golang接口值类型接收者和指针类型接收者
  • golang接口和类型的关系
  • 一个类型实现多个接口
  • 多个类型实现同一个接口
  • golang接口嵌套

接口

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{} // 这里编译错误,提示只实现了一个接口
}

golang接口值类型接收者和指针类型接收者

这个话题,本质上和方法的值类型接收者和指针类型接收者,的思考方法是一样的,值接收者是一个拷贝,是一个副本,而指针接收者,传递的是指针。
举例
定义一个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: &{黑黑}

golang接口和类型的关系

  1. 一个类型可以实现多个接口
  2. 多个类型可以实现同一个接口(多态)

一个类型实现多个接口

一个类型实现多个接口,例如:有一个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...

golang接口嵌套

接口可以通过嵌套,创建新的接口。例如:飞鱼,既可以飞,又可以游泳。我们创建一个飞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...

你可能感兴趣的:(GoLang,golang,学习,开发语言)