Content #
// $GOROOT/src/runtime/runtime2.go
type iface struct {
tab *itab
data unsafe.Pointer
}
iface 用于表示非空的拥有方法的接口 interface 类型变量。
iface 除了要存储动态类型信息之外,还要存储接口本身的信息(接口的类型信息、方法列表信息等)以及动态类型所实现的方法的信息,因此 iface 的第一个字段指向一个itab类型结构。itab 结构的定义如下:
// $GOROOT/src/runtime/runtime2.go
type itab struct {
inter *interfacetype
_type *_type
hash uint32 // copy of _type.hash. Used for type switches.
_ [4]byte
fun [1]uintptr // variable sized. fun[0]==0 means _type does not implement inter.
}
itab 结构中的字段_type(参看 eface结构)则存储着这个接口类型变量的动态类型的信息。字段fun则是动态类型已实现的接口方法的调用地址数组。 itab 结构中的第一个字段inter指向的 interfacetype 结构,存储着这个接口类型自身的信息。interfacetype 结构由类型信息(typ)、包路径名(pkgpath)和接口方法集合切片(mhdr)组成。
// $GOROOT/src/runtime/type.go
type interfacetype struct {
typ _type
pkgpath name
mhdr []imethod
}
我们来看一个用 iface 表示非空接口类型变量的例子:
type T struct {
n int
s string
}
func (T) M1() {}
func (T) M2() {}
type NonEmptyInterface interface {
M1()
M2()
}
func main() {
var t = T{
n: 18,
s: "hello, interface",
}
var i NonEmptyInterface = t
}
和 eface 比起来,iface 的表示稍微复杂些。我也画了一幅表示上面
NonEmptyInterface 接口类型变量在 Go 运行时表示的示意图:
