Go Reflection Panic:使用interface {}作为类型调用

时间:2018-04-19 15:33:49

标签: go reflection interface call panic

我正在修补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()

1 个答案:

答案 0 :(得分:1)

恐慌信息解释了这个问题。 reflect.ValueOf(&xCopy)中的值的类型为*interface{}。此值的Elem()的类型为interface{}。函数参数的类型为string。即使interface{}包含stringinterface{}值也不是string值。

请注意,接口值的地址是指向接口的指针,而不是指向接口中值的指针。