go语言接口与断言
go语言接口与断言
类型
接口也是go语言中的一种类型,它能够出现在变量的定义、函数的入参和返回值中并对它们进行约束,不过go语言中有两种略微不同的接口,一种是带有一组方法的接口,另一种是不带任何方法的interface{}
go语言使用runtime.iface表示第一种接口,使用runtime.eface表示第二种不包含任何方法的interface{},两种接口虽然都是用interface声明,但是由于后者在go语言中很常见,所以在实现时使用了特殊类型。
数据结构
// 没有方法的interface
type eface struct {
_type *_type
data unsafe.Pointer
}
// 记录着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
// 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
}
// 有方法的interface
type iface struct {
tab *itab
data unsafe.Pointer
}
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.
}
// interface数据类型对应的type
type interfacetype struct {
typ _type
pkgpath name
mhdr []imethod
}
eface结构体只包含指向底层数据和类型的两个指针,iface结构体有指向原始数据的指针data,但更重要的是runtime.itab类型的tab字段。
类型结构体
runtime._type是go语言类型的运行时表示。其中包含了很多类型的元信息,例如类型的大小、哈希、对齐以及种类。
- size字段存储了类型占用的内存空间,为内存空间的分配提供信息。
- hash字段能够帮助我们快速确定类型是否相等。
itab结构体
runtime.itab结构体是接口类型的核心组成部分,每一个runtime.itab都占32字节。我们可以将其看成接口类型和具体类型的组合,他们分别用inner和_type两个字段表示。
除inner和_type这两个用于表示类型的字段外,上述结构体中的另外两个字段也有自己的作用。
- hash是对_type.hash的复制,当我们想将interface类型转换成具体类型时,可以使用该字段快速判断目标类型和具体类型runtime._type是否一致。
- fun是一个动态大小的数组,它是一个用于动态派发的虚函数表,存储了一组函数指针。虽然该变量被声明成大小固定的数组,但在使用时会通过原始指针获取其中的数据,所以fun数组中保存的元素数量是不确定的。
浙公网安备 33010602011771号