使用的一般步骤:
- 定义一个接口
- 定义一个以此接口作为第一个参数的函数
- 定义多个结构体
- 多个结构体实现该接口
- 使用接口:调用接口声明的函数,把结构体作为第一个参数传进去,或者使用接口类型直接调用方法。
- 如果通过结构体直接调用方法,就没接口什么事了,也不涉及多态。
go 的鸭子类型归功于编译器的隐式类型转换。
调用接口规定的函数时,会隐式把传进去的结构体隐式转为接口类型。
不管方法的接受者是什么类型,该类型(不是接口类型)的值或指针都可以调用。
值类型调用者,指针类型接受者,使用值的引用来调用此方法。
指针类型调用者,值类型接受者,指针被解引用为值。
而对于接口类型,想调用方法,需要记住:
如果实现了接收者是值类型的方法,会隐含地也实现了接收者是指针类型的方法。
接受者定义为值类型,还是指针类型,由接受者类型本身来决定!
内置原始类型,int、string等,值接受类型。
内置引用类型,slice,map,interface,channel,值接受类型;声明它们时实质是创建了一个 header,复制它们实质复制的是 header,header 本身就为复制而设计的。
类型不具备原始本质 ,不能被安全的复制,就应该设计为指针接受类型。如文件结构体 struct file。
go 类型
_type 结构体是 go 语言实现各种结构体的基础 ,也就是 go 的各种结构体是在 _type 结构基础上增加一些字段。
这是反射实现的基础。
type _type struct {// 类型大小size uintptrptrdata uintptr// 类型的 hash 值hash uint32// 类型的 flag,和反射相关tflag tflag// 内存对齐相关align uint8fieldalign uint8// 类型的编号,有bool, slice, struct 等等等等kind uint8alg *typeAlg// gc 相关gcdata *bytestr nameOffptrToThis typeOff}
接口类型定义:
type iface struct {tab *itabdata unsafe.Pointer}
接口包括两字段 tab 是接口表指针,指向动态类型,data 是数据指针,指向动态值。
当且仅当这两者都为 nil 时,接口值才为 nil 。
类型断言,对接口类型进行转换。
