golang reflect.Typeof & reflect.Valueof

0x00 写在前面

reflect.Typeof 和 reflect.Valueof 这俩方法都是 reflect 包提供的用以获取变量动态类型的方法,也就是 golang 中的反射。

0x01 同异

首先看看这俩的源码

// TypeOf returns the reflection Type that represents the dynamic type of i.
// If i is a nil interface value, TypeOf returns nil.
// TypeOf返回反映i的动态类型的反射类型。
// 如果i是nil接口值,TypeOf返回nil。
func TypeOf(i any) Type {
	eface := *(*emptyInterface)(unsafe.Pointer(&i))
	// Noescape so this doesn't make i to escape. See the comment
	// at Value.typ for why this is safe.
	return toType((*abi.Type)(noescape(unsafe.Pointer(eface.typ))))
}

// 这边我们再继续跟进 toType 的方法调用,能够看到最后的 toRType 
func toRType(t *abi.Type) *rtype {
	return (*rtype)(unsafe.Pointer(t))
}

从上述 Typeof 的源码中能够很清晰的看到, Typeof 返回的结果中指保留了原参数的动态类型信息——*rtype ,也就是我们无法再通过返回值获取到原先传入参数的原始值是多少(其余跟原参数值相关的操作当然也没办法进行)。

// ValueOf returns a new Value initialized to the concrete value
// stored in the interface i. ValueOf(nil) returns the zero Value.
// ValueOf返回一个存储在接口中初始化为具体值的新值
// 。ValueOf(nil)返回零值。
func ValueOf(i any) Value {
	if i == nil {
		return Value{}
	}

	if !go121noForceValueEscape {
		escapes(i)
	}

	return unpackEface(i)
}

// unpackEface converts the empty interface i to a Value.
func unpackEface(i any) Value {
    // 这一步可以看到跟 Typeof 是一致的
	e := (*emptyInterface)(unsafe.Pointer(&i))
	// NOTE: don't read e.word until we know whether it is really a pointer or not.
	t := e.typ
	if t == nil {
		return Value{}
	}
    
    // 这一步拿到基础类型
	f := flag(t.Kind())
	if t.IfaceIndir() {
		f |= flagIndir
	}
	return Value{t, e.word, f}
}

从 Valueof 的源码能看出,Valueof 返回值中保留了原参数的动态类型以及原始值信息,这也就代表着我们不仅能够针对参数的动态类型做一些操作 reflect.Valueof(xx).Type(),对其原始值也能够进行处理。

0x02 写在后面

综上,Valueof 似乎要比 Typeof 拓展性更强。但当只需要判断参数类型时,往往 Typeof 就已经够用,没必要使用 Valueof 再绕一道弯子。浅薄见解,欢迎指正。

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值