Go中reflect.Value传入interface后调用Pointer()失败的原因及解决
问题原因
- 当你将已有的
reflect.Value类型的valueGot/valueWant传入入参为interface{}的GetFunctionName时,函数内部执行reflect.ValueOf(i)得到的是**reflect.Value实例本身的反射对象**,而非它内部存储的func类型值的反射对象。 - 此时调用
Pointer()方法,实际是尝试获取reflect.Value结构体实例的指针,而非底层func的入口地址,自然会报错或得到错误结果。 - 而你在
SelectCompareStruct内部直接调用valueGot.Pointer()时,操作的就是存储了func值的reflect.Value对象,所以可以正常拿到func地址。
解决方案
修改GetFunctionName,兼容「入参是普通值」和「入参本身就是reflect.Value实例」两种场景,保留入参为interface{}的通用性,修改后的代码如下:
func GetFunctionName(i interface{}) string { var v reflect.Value // 先判断传入的是否已经是reflect.Value类型 if rv, ok := i.(reflect.Value); ok { v = rv } else { v = reflect.ValueOf(i) } // 增加类型校验,避免非func类型调用Pointer触发panic if v.Kind() != reflect.Func { return "" // 也可根据需求返回自定义的非法值标记 } return runtime.FuncForPC(v.Pointer()).Name() }
修改后不管是直接传入普通func变量,还是传入反射得到的reflect.Value实例,都可以正常获取函数名,无需调整上层调用逻辑,也保留了函数的通用性。
内容的提问来源于stack exchange,提问作者tao4free
相关产品推荐
相关产品推荐

