Golang学习笔记—接口

166 阅读3分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第26天,点击查看活动详情

接口

Go语言中的接口时一种特殊的数据类型,定义格式如下:

type name interface{
    method_name() retrun_type
}

空接口

通常用空接口代指任意类型

空接口定义一个切片,内部可以存放任意类型数据

Demo01

package main
​
import "fmt"//定义空接口
type Base interface {
}
​
func main() {
   //定义一个切片,内部可以存放任意类型
   list := make([]Base, 0) //简写:list:=make([]interface{},0)
   //切片中添加字符串类型
   list = append(list, "Sentiment")
   //切片中添加整型
   list = append(list, 18)
   //切片中添加浮点型
   list = append(list, 9.9)
   fmt.Println(list)
}

结果:

[Sentiment 18 9.9]

空接口也可以作为函数的参数传入

package main
​
import "fmt"func print(arg interface{}) {
   fmt.Println(arg)
}
​
type Person struct {
   name string
}
​
func main() {
   print("Sentiment")
   print("666")
   print(9.9)
   print(Person{name: "Sentiment"})
}

结果:

Sentiment
666
9.9
{Sentiment}

类型转换

由于接口只是代指这些数据类型(在内部其实是转换为了接口类型),想要再获取数据中的值时,需要再将接口转换为指定的数据类型。

package main
​
import "fmt"func print(arg interface{}) {
   tp, ok := arg.(Person)
   if ok {
      fmt.Println(tp)
   } else {
      fmt.Println("转换失败")
   }
}
​
type Person struct {
   name string
}
​
func main() {
   print("Sentiment")
   print("666")
   print(9.9)
   print(Person{name: "Sentiment"})
}

结果:

转换失败
转换失败
转换失败
{Sentiment}

非空接口

Demo02

package main
​
import "fmt"type USB interface {
   read()
   write()
}
​
type Computer struct {
   name string
}
​
func (c Computer) read() {
   fmt.Println("this is read")
}
func (c Computer) write() {
   fmt.Println("this is write")
}
func main() {
   var usb USB
   usb = Computer{}
   usb.read()
}

结果:

this is read

类型

接口值类型

Demo03

package main
​
import "fmt"type Pet interface {
   eat()
}
​
type Dog struct {
   name string
}
​
func (dog Dog) eat(string2 string) string {
   dog.name = "Mumu"
   fmt.Println(string2)
   return "delicious"
}
func main() {
   dog := Dog{
      name: "Tana",
   }
   s := dog.eat("vegetable")
   fmt.Println(s)
   fmt.Println(dog)
}

结果:

vegetable
delicious
{Tana}

指针类型

指针类型的在调用eat()时,dog.name的值会发生改变

package main
​
import "fmt"type Pet interface {
   eat()
}
​
type Dog struct {
   name string
}
​
func (dog *Dog) eat(string2 string) string {
   dog.name = "Mumu"
   fmt.Println(string2)
   return "delicious"
}
func main() {
   dog := &Dog{
      name: "Tana",
   }
   s := dog.eat("vegetable")
   fmt.Println(s)
   fmt.Println(dog)
}

结果:

vegetable
delicious
&{Mumu}

接口和类型的关系

1、一个类型可以实现多个接口

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

一个类型可以实现多个接口

例:一个手机Mobile可以实现两个接口,Player播放音乐,Video播放视频

Player接口

type Player interface {
   Music()
}

Video接口

type Video interface {
   Video()
}

Mobile结构体

type Mobile struct {
}

Demo04

package main
​
import "fmt"type Player interface {
   Music()
}
type Video interface {
   Video()
}
type Mobile struct {
}
​
func (m Mobile) Music() {
   fmt.Println("this is music")
}
func (m Mobile) Video() {
   fmt.Println("this is video")
}
func main() {
   var music Player
   music = Mobile{}
   music.Music()
​
   var video Video
   video = Mobile{}
   video.Video()
}

结果:

this is music
this is video

多个类型实现一个接口

例:一个宠物接口Pet,猫类型Cat和狗类型Dog都可以实现该接口(多态)

Pet接口

type Pet1 interface {
   eat()
}

Dog结构体

type Dog1 struct {
}

Cat结构体

type Cat struct {
}

Demo05

package main
​
import "fmt"type Pet1 interface {
   eat()
}
type Dog1 struct {
}
type Cat struct {
}
​
func (dog Dog1) eat() {
   fmt.Println("Dog eat!")
}
func (cat Cat) eat() {
   fmt.Println("Cat eat!")
}
func main() {
   var p Pet1
   p = Dog1{}
   p.eat()
   p = Cat{}
   p.eat()
}

结果:

Dog eat!
Cat eat!

接口嵌套

接口可以通过嵌套,创建新的接口。例:飞鱼既可以飞,也可以游泳。

飞fly接口

type fly interface {
   fly()
}

游泳swim接口

type swim interface {
   swim()
}

组合接口flyfish

type flyfish interface {
   fly
   swim
}

fish结构体

type fish struct 
}

Demo06

package main
​
import "fmt"type fly interface {
   fly()
}
type swim interface {
   swim()
}
type flyfish interface {
   fly
   swim
}
type fish struct {
}
​
func (f fish) fly() {
   fmt.Println("fly!")
}
func (f fish) swim() {
   fmt.Println("swim!")
}
func main() {
   var f flyfish
   f = fish{}
   f.fly()
   f.swim()
}

结果:

fly!
swim!

OCP设计原则

OCP即开-闭原则,在设计模块时,软件应该使这个模块在不被修改的前提下被扩展,即可扩展但不可以修改删除

例:接口一个Person可以有dog和cat并且有care功能

Demo07

package main
​
import "fmt"type Pet2 interface {
   eat()
}
type dog2 struct {
}
​
func (dog dog2) eat() {
   fmt.Println("dog eat!")
}
​
type cat2 struct {
}
​
func (cat cat2) eat() {
   fmt.Println("cat eat!")
}
​
type Person2 struct {
}
​
func (per Person2) care(pet Pet2) {
   pet.eat()
}
​
func main() {
   dog := dog2{}
   cat := cat2{}
   per := Person2{}
   per.care(dog)
   per.care(cat)
}

结果:

dog eat!
cat eat!

此时如果想再加一个pig,则不需要对原有的care方法等进行修改