接口是一种类型

Go语言中接口(interface)是一种类型,一种抽象的类型。它规定了变量有哪些方法

interface是一组method的集合,是duck-type programming的一种体现。接口做的事情就像是定义一个协议(规则),只要一台机器有洗衣服和甩干的功能,我就称它为洗衣机。不关心属性(数据),只关心行为(方法)

在编程中会遇到以下场景:

:::warning 我不关心一个变量是什么类型,我只关心能调用它的什么方法。

:::

接口的定义

  1. type 接口名 interface {
  2. 方法名1(参数1 参数2...)(返回值1,返回值2,...)
  3. 方法名2(参数1 参数2...)(返回值1,返回值2,...)
  4. ...
  5. }

用来给变量、参数、返回值等设置类型。

实战

  1. type speak interface {
  2. Say() string
  3. }
  4. type Cat struct{}
  5. func (c Cat) Say() string { return "喵喵喵" }
  6. type Dog struct{}
  7. func (d Dog) Say() string { return "汪汪汪" }
  8. func main() {
  9. c := Cat{}
  10. fmt.Println("猫:", c.Say())
  11. d := Dog{}
  12. fmt.Println("狗:", d.Say())
  13. }
  14. type Cat struct{}
  15. func (c Cat) Say() string { return "喵喵喵" }
  16. type Dog struct{}
  17. func (d Dog) Say() string { return "汪汪汪" }
  18. func main() {
  19. c := Cat{}
  20. fmt.Println("猫:", c.Say())
  21. d := Dog{}
  22. fmt.Println("狗:", d.Say())
  23. }

接口的实现

:::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类型的变量能够存储dogcat类型的变量。
  1. func main() {
  2. var x Sayer // 声明一个Sayer类型的变量x
  3. a := cat{} // 实例化一个cat
  4. b := dog{} // 实例化一个dog
  5. x = a // 可以把cat实例直接赋值给x
  6. x.say() // 喵喵喵
  7. x = b // 可以把dog实例直接赋值给x
  8. x.say() // 汪汪汪
  9. }
这里其实能感觉出来和java里面接口的相似之处了。 类型看左边,实现看右边

Tips: 观察下面的代码,体味此处_的妙用

  1. // 摘自gin框架routergroup.go
  2. type IRouter interface{ ... }
  3. type RouterGroup struct { ... }
  4. var _ IRouter = &RouterGroup{} // 确保RouterGroup实现了接口IRouter