interface 分两种空接口(eface)和非空接口(有方法定义的接口)
type eface struct {
_type *_type // 具体类型信息的指针
data unsafe.Pointer // 指向实际存储的数据
}
也就是定义了指向位置的指针和指向类型的指针。
例子:
var i interface{}
i = 42
_type 指向 int 的类型信息。
data 存放 42 的内存地址。
type iface struct {
tab *itab // 方法表,存储类型和接口的对应关系
data unsafe.Pointer // 指向具体数据
}
type itab struct {
inter *interfacetype // 接口类型信息(方法列表)
_type *_type // 具体类型信息
hash uint32 // 类型的哈希值
_ [4]byte
fun [1]uintptr // 方法表,存储方法的函数指针
}
非空接口比空接口多了一层 itab(接口表),因为要支持方法调用
通过 tab.fun 来找到方法的实际实现函数地址。
例子:
type Stringer interface {
String() string
}
type MyInt int
func (m MyInt) String() string {
return fmt.Sprintf("%d", m)
}
var s Stringer
s = MyInt(42)
评论