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数组中保存的元素数量是不确定的。
posted @ 2023-06-07 23:49  每天提醒自己要学习  阅读(37)  评论(0)    收藏  举报