接口
接口类型具体描述了一系列方法的集合,一个实现了这些方法的具体类型是这个接口类型的实例。接口类型不能被实例化
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
}