前言
在 Go
语言没有泛型之前,接口可以作为一种替代实现,也就是万物皆为的 interface
。那到底 interface
是怎么设计的底层结构呢?下面咱们透过底层分别看一下这两种类型的接口原理。感兴趣的小伙伴们可以参考借鉴,希望对大家能有所帮助。
interface数据结构
golang
中的接口分为带方法的接口和空接口。 带方法的接口在底层用iface
表示,空接口的底层则是eface
表示。下面咱们透过底层分别看一下这两种数据结构。
iface
iface表示的是包含方法的interface;例如:
type Test interface{
test()
}
底层源代码是:
//runtime/runtime2.go
//非空接口
type iface struct {
tab *itab
data unsafe.Pointer //data是指向真实数据的指针
}
type itab struct {
inter *interfacetype //描述接口自己的类型
_type *_type //接口内部存储的具体数据的真实类型
link *itab
hash uint32 // copy of _type.hash. Used for type switches.
bad bool // type does not implement interface
inhash bool // has this itab been added to hash?
unused [2]byte
fun [1]uintptr // fun是指向方法集的指针。它用于动态调度。
}
//runtime/type.go
type _type struct {
size uintptr
ptrdata uintptr // size of memory prefix holding all pointers
hash uint32
tflag tflag
align uint8
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
}
和eface相同的是都有指向具体数据的指针data字段。 不同的是_type变成了tab。
- hash 是对 _type.hash 的拷贝,当我们想将 interface 类型转换成具体类型时,可以使用该字段快速判断目标类型和具体类型 runtime._type 是否一致;
- fun 是一个动态大小的数组,它是一个用于动态派发的虚函数表,存储了一组函数指针。虽然该变量被声明成大小固定的数组,但是在使用时会通过原始指针获取其中的数据;
eface
eface顾名思义 empty interface,代表的是不包含方法的interface,例如:
type Test interface {}
因为空接口不包含任何方法,所以它的结构也很简单,底层源代码是:
//空接口
type eface struct {
_type *_type //接口内部存储的具体数据的真实类型
data unsafe.Pointer //data是指向真实数据的指针
}
//runtime/type.go
type _type struct {
size uintptr
ptrdata uintptr // size of memory prefix holding all pointers
hash uint32
tflag tflag
align uint8
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
}
eface 结构体主要包含两个字段,共16字节。
- _type:这个是运行时 runtime._type 指针类型,表示数据类型
- data: 表示的数据指针
总结
Go语言底层对非空interface
和空interface
实现上做了区分。空interface
的底层结构是eface
结构。它与iface
的区别在于,它拥有的不再是 *itab
类型数据,而是 _type
类型的数据。是因为,eface
面向的是空的interface
数据,既然是空的interface
,那么只需要用 *_type
代表类型,data
字段指向具体数据即可。这里的 *_type
是此interface
代表的数据的类型。
到此这篇关于深入了解Golang interface{}的底层原理实现的文章就介绍到这了,更多相关Golang interface{}内容请搜索编程网以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程网!