go反射与接口

go反射的秘密一文中,我从源代码的角度分析了go反射的相关细节,但是在那篇文章中,还是留下了两个疑问:

  1. 为什么TypeOf函数的实现是直接强制类型转换?
  2. 一个具体类型的变量是如何转成interface的?

由于当时的我年少无知,没能解答出这两个问题。时过境迁,再次读书的时候偶然明悟,遂作此文以解惑。

让我们再次回顾一下TypeOf函数的源码:

/*--type.go--*/
func TypeOf(i interface{}) Type {
	eface := *(*emptyInterface)(unsafe.Pointer(&i))
	return toType(eface.typ)
}

/* ... ... */

type emptyInterface struct {
	typ  *rtype
	word unsafe.Pointer
}

其实从源码中我们也能大概推测是事情的原因,那就是interface类型和emptyInterface类型必然有着相同的数据结构!只是当时没能想到,也就失去了求证的机会。

在go源码runtime包的runtime2.go中,有如下代码:

// 非空接口类型
type iface struct {
	tab  *itab
	data unsafe.Pointer
}

// 空接口类型
type eface struct {
	_type *_type
	data  unsafe.Pointer
}

可以看到emptyInterfaceeface的定义是如此的相似,以至于让我们迫不及待的想去看看rtype_type的定义是否也相同。

// rtype is the common implementation of most values.
// It is embedded in other struct types.
//
// rtype must be kept in sync with ../runtime/type.go:/^type._type.
type rtype struct {
	size       uintptr
	ptrdata    uintptr // number of bytes in the type that can contain 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
	equal     func(unsafe.Pointer, unsafe.Pointer) bool
	gcdata    *byte   // garbage collection data
	str       nameOff // string form
	ptrToThis typeOff // type for pointer to this type, may be zero
}

// Needs to be in sync with ../cmd/link/internal/ld/decodesym.go:/^func.commonsize,
// ../cmd/compile/internal/gc/reflect.go:/^func.dcommontype and
// ../reflect/type.go:/^type.rtype.
// ../internal/reflectlite/type.go:/^type.rtype.
type _type struct {
	size       uintptr
	ptrdata    uintptr // size of memory prefix holding all pointers
	hash       uint32
	tflag      tflag
	align      uint8
	fieldAlign uint8
	kind       uint8
	equal func(unsafe.Pointer, unsafe.Pointer) bool
	gcdata    *byte
	str       nameOff
	ptrToThis typeOff
}

惊喜单不意外的是,它们两的确是一模一样,甚至注释中还贴心的写着它们必须保持同步。至于TypeOf函数直接强转为emptyInterface类型,那是因为TypeOf函数的参数就是空接口。

现在的问题就是一个具体类型的值是如何转换为ifaceeface的,这其实是编译器帮我们实现的,其中的字段也是由编译器进行填充的。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值