interface 的数据结构
eface 和 iface
源码:
type iface struct {
tab *itab
data unsafe.Pointer
}
type eface struct {
_type *_type
data unsafe.Pointer
}
- eface 表示空的 interface{}
- iface 表示至少带有一个函数的 interface
data
- data是一个指针类型,指向被赋值对象 (或者说用来保存实际变量的地址)
因为一个interface{}可以接收值类型和指针类型,所以这里还是分成两种情况
- 如果实际类型是值类型,interface 会在堆上为这个值分配一块内存,然后 data 指向拷贝后的对象。
- 如果实际类型是指针类型,会拷贝指针,就相当于直接指向被赋值的对象
itab
源码:
// layout of Itab known to compilers
// allocated in non-garbage-collected memory
// Needs to be in sync with
// ../cmd/compile/internal/reflectdata/reflect.go:/^func.WriteTabs.
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 表示 interface 和 实际类型的转换信息。对于每个 interface 和实际类型,只要在代码中存在引用关系, go 就会在运行时为这一对具体的 <Interface, Type> 生成 itab 信息。
- inter 指向对应的 interface 的类型信息。
- type 和 eface 中的一样,指向的是实际类型的描述信息 _type
- fun 为函数列表,表示对于该特定的实际类型而言,interface 中所有函数的地址。
_type
源码(GOROOT/src/runtime/type.go):
// Needs to be in sync with ../cmd/link/internal/ld/decodesym.go:/^func.commonsize,
// ../cmd/compile/internal/reflectdata/reflect.go:/^func.dcommontype and
// ../reflect/type.go:/^type.rtype.
// ../internal/reflectlite/type.go:/^type.rtype.
type _type struct {
size uintptr
ptrdata uintptr // size of memory prefix holding all pointers
hash uint32
tflag tflag
align uint8
fieldAlign uint8
kind uint8
// function for comparing objects of this type
// (ptr to object A, ptr to object B) -> ==?
equal func(unsafe.Pointer, unsafe.Pointer) bool
// gcdata stores the GC type data for the garbage collector.
// If the KindGCProg bit is set in kind, gcdata is a GC program.
// Otherwise it is a ptrmask bitmap. See mbitmap.go for details.
gcdata *byte
str nameOff
ptrToThis typeOff
}
_type 表示类型信息。每个类型的 _type 信息由编译器在编译时生成。其中:
- size 为该类型所占用的字节数量。
- kind 表示类型的种类,如 bool、int、float、string、struct、interface 等。
- str 表示类型的名字信息,它是一个 nameOff(int32) 类型,通过这个 nameOff,可以找到类型的名字字符串
- 灰色的 extras 对于基础类型(如 bool,int, float 等)是 size 为 0 的,它为复杂的类型提供了一些额外信息。例如为 struct 类型提供 structtype,为 slice 类型提供 slicetype 等信息。
- 灰色的 ucom 对于基础类型也是 size 为 0 的,但是对于 type Binary int 这种定义或者是其它复杂类型来说,ucom 用来存储类型的函数列表等信息。
- 注意 extras 和 ucom 的圆头箭头,它表示 extras 和 ucom 不是指针,它们的内容位于 _type 的内存空间中。
interfacetype
interfacetype
源码(GOROOT/src/runtime/type.go):
type interfacetype struct {
typ _type
pkgpath name
mhdr []imethod
}
interfacetype 也并没有什么神奇的地方,只是 _type 为 interface 类型提供的另一种信息罢了。 它包括这个 interface 所申明的所有函数信息。