我正在修补Go中的反思,我遇到了一个有趣的场景。 call1()
工作(返回"hello!"
)而call2()
恐慌reflect: Call using interface {} as type string
。
在下面的代码中,call1()
和call2()
之间的唯一区别是inValue
的创建和初始化方式。我可以清楚地看到为什么call1()
会导致inValue
成为string
,而call2()
会导致inValue
成为interface
所以我的问题不是为什么我的代码产生这个,而是:
为什么Go不能在第二种情况下执行函数调用?我认为接口仍然包含成功调用方法的所有必要信息,因为xCopy
仍然真正表示下面的字符串。 (是的,我确实已经阅读了laws of reflection)
我会注意到,由于我正在做的事情,我做需要inValue
才能在函数中设置(因此使用指针)。
谢谢!
func main() {
fmt.Println(call1(foo, "hello"))
fmt.Println(call2(foo, "hello"))
}
func foo(x string) string {
return x + "!"
}
func call1(f, x interface{}) interface{} {
fValue := reflect.ValueOf(f)
inValue := reflect.New(reflect.TypeOf(x)).Elem()
inValue.Set(reflect.ValueOf(x))
inValue.Set(fValue.Call([]reflect.Value{inValue})[0])
return inValue.Interface()
}
func call2(f, x interface{}) interface{} {
fValue := reflect.ValueOf(f)
xCopy := x
inValue := reflect.ValueOf(&xCopy).Elem()
inValue.Set(fValue.Call([]reflect.Value{inValue})[0])
return inValue.Interface()
}
修改
或许问题变成:为什么不为interface
分配真实类型而不是inValue := reflect.ValueOf(&xCopy).Elem()
?
答案 0 :(得分:1)
恐慌信息解释了这个问题。 reflect.ValueOf(&xCopy)
中的值的类型为*interface{}
。此值的Elem()
的类型为interface{}
。函数参数的类型为string
。即使interface{}
包含string
,interface{}
值也不是string
值。
请注意,接口值的地址是指向接口的指针,而不是指向接口中值的指针。