golang interface的内部实现分类两种。
eface= empty interface
iface= not empty interface
eface为没有method的interface,如
type a interface{}
底层结构为
type eface struct {
_type *_type
data unsafe.Pointer
}
type _type struct {
size uintptr // type size
ptrdata uintptr // size of memory prefix holding all pointers
hash uint32 // hash of type; avoids computation in hash tables
tflag tflag // extra type information flags
align uint8 // alignment of variable with this type
fieldalign uint8 // alignment of struct field with this type
kind uint8 // enumeration for C
alg *typeAlg // algorithm table
gcdata *byte // garbage collection data
str nameOff // string form
ptrToThis typeOff // type for pointer to this type, may be zero
}
_type
iface底层结构
type iface struct {
tab *itab
data unsafe.Pointer
}
// 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
inhash int32 // has this itab been added to hash?
fun [1]uintptr // variable sized
}
iface 结构中最重要的是 itab 结构。itab 可以理解为 pair\ 。当然 itab 里面还包含一些其他信息,比如 interface 里面包含的 method 的具体实现。
其中 interfacetype 包含了一些关于 interface 本身的信息,比如 package path,包含的 method。上面提到的 iface 和 eface 是数据类型(built-in 和 type-define)转换成 interface 之后的实体的 struct 结构,而这里的 interfacetype 是我们定义 interface 时候的一种抽象表示。
_type 表示 concrete type。
fun 表示的 interface 里面的 method 的具体实现。比如 interface type 包含了 method A, B,则通过 fun 就可以找到这两个 method 的具体实现。
在来看下这个问题:
func Foo(x interface{}) {
if x == nil {
fmt.Println("empty interface")
return
}
fmt.Println("non-empty interface")
}
func main() {
var y *int = nil
Foo(y)
}
y 是一个int指针,指向了nil。
x interface{} = y
所以x结构体本身不是nil,而是里面的data指针为nil。
参考