Go 接口 | 青训营

39 阅读2分钟

接口

接口类型具体描述了一系列方法的集合,一个实现了这些方法的具体类型是这个接口类型的实例。接口类型不能被实例化

type ReadWriter interface {
    Reader
    Writer
}

Go 语言对接口实现的规定如下:

  • 实现接口的方法时,如果接收者都是 T 类型,称作 T 类型实现了该接口
  • 实现接口的方法时,如果接收者都是 *T 类型,称作 *T 类型实现了该接口
  • 如果方法的接收者为 T 类型,可以使用任意 *T 类型的接收者来调用,因此在 Go 语言中规定,如果通过 T 类型实现了一个接口,那么 *T 类型也自动实现了该接口
  • 如果方法的接收者为 *T 类型,仅能通过可取地址的 T 类型接收者来调用,不能用不可取地址的 T 类型接收者(比如字面量)来调用,因此在 Go 语言中规定,如果通过 *T 类型实现了一个接口,那么 T 类型并没有实现该接口

接口变量

当使用接口类型声明一个变量,这个变量称作接口变量。给接口变量赋值需要满足如下条件:仅当一个表达式的值为 nil 或实现了该接口时,这个表达式才可以赋值给该接口变量

  • 如果把 T 类型的实例赋值给接口变量,那么将拷贝该实例的数据结构到接口变量中
  • 如果把 *T 类型的实例指针赋值给接口变量,那么仅拷贝指针值到接口变量中
  • 如果将一个接口变量赋值给另一个接口变量,两个接口变量将会引用同一个实例

接口值

接口值由两个部分组成,一个是具体的类型,另一个是该类型所对应的值。它们被称为接口的动态类型和动态值

在 Go 语言中,变量默认初始化为其零值。接口的零值就是把它的动态类型和动态值都设置为 nil

一个接口值是否为 nil 取决于它的动态类型,所以接口的零值是一个 nil 接口值,因为它的动态类型是 nil

如果两个接口值都是 nil 或者二者的动态类型完全一致且动态值都相等,那么两个接口值相等

空接口

interface{} 不包含任何方法,正因为如此,所有的类型都实现了 interface{}interface{} 可用来存储任意类型的值。它有点类似 C 语言的 void * 类型

type eface struct { // 16 字节
    _type *_type
    data  unsafe.Pointer
}