GO Interface内部实现的理解
我们知道GO可以通过定义接口,将具体的实现和调用完全分离,其本质就是引入一个中间层对不同的模块进行解耦,上层的模块就不需要依赖某一个具体的实现,而是只需要依赖一个定义好的接口。那么,在理解了如何使用Go的interface后,了解其内部实现,有助于我们更好的使用这套机制。作为上篇的补充,这次把对interface的内部实现做了个整理。
interface底层上是分别由两个struct实现:iface和eface。eface表示empty interface,不包含任何方法,iface 表示 non-empty interface,即包含方法的接口。从概念上来讲,iface和eface均由两部分组成:type和value,type表示interface的类型描述,主要提供concrete type相关的信息,value指向interface绑定的具体数据。

具体类型实例传递给接口称为接口的实例化,这里有个地方值得注意,Interface变量默认值为nil,需要初始化后才有意义。
eface
先从较简单的eface看起,空接口eface结构比较简单,由两个属性构成,一个是类型信息_type,一个是数据信息。其数据结构声明如下:
type eface struct {
_type *_type
data unsafe.Pointer
}
其中_type是GO语言中所有类型的公共描述,Go语言几乎所有的数据结构都可以抽象成 _type,是所有类型的公共描述, type负责决定data应该如何解释和操作, type的结构代码如下:
type _type struct {
size uintptr
ptrdata uintptr // size of memory prefix holding all pointers
hash uint32 // 类型哈希
tflag tflag
align uint8 // _type作为整体变量存放时的对齐字节数
fieldalign uint8
kind uint8
alg *typeAlg
// 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 for pointer to this type, may be zero
}
data表示指向具体的实例数据,由于Go的参数传递规则为值传递,如果希望可以通过interface对实例数据修改,则需要传入指针,此时data指向的是指针的副本,但指针指向的实例地址不变,仍然可以对实例数据产生修改。

iface
iface 表示 non-empty interface 的数据结构,非空接口初始化的过程就是初始化一个iface类型的结构,其中data的作用同eface的相同,这里不再多加描述。
type iface struct {
tab *itab
data unsafe.Pointer
}
iface结构中最重要的是itab结构(结构如下),每一个
itab
都占 32 字节的空间。itab可以理解为pair<interface type, concrete type> 。itab里面包含了interface的一些关键信息,比如method的具体实现。
// layout of Itab known to compilers
// allocated in non-garbage-collected memory
// Needs to be in sync with
// ../cmd/compile/internal/gc/reflect.go:/^func.dumptypestructs.
type itab struct {
inter *interfacetype // 接口自身的元信息
_type *_type // 具体类型的元信息
link *itab
bad int32
hash int32 // _type里也有一个同样的hash,此处多放一个是为了方便运行接口断言
fun [1]uintptr // 函数指针,指向具体类型所实现的方法
type interfacetype struct {
typ _type
pkgpath name
mhdr []imethod