【问题标题】:Go Reflection Panic: Call using interface{} as typeGo Reflection Panic:使用 interface{} 作为类型调用
【发布时间】:2018-09-30 04:27:58
【问题描述】:

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

编辑

也许问题就变成了:为什么 Go 不为 inValue := reflect.ValueOf(&xCopy).Elem() 分配真正的类型,而不是 interface

【问题讨论】:

    标签: go reflection interface call panic


    【解决方案1】:

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

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

    【讨论】:

    • 是的,虽然 inValue 不能设置。我忘了在我的要求中提到这一点。更新了问题。
    • @menehune23 鉴于问题中提供的代码,不清楚您在问什么。更新问题以演示如何使用可设置值。无论如何,我回答了提出的问题。
    • 是的,现在更新了。虽然我会争辩说你并没有真正回答我的问题。我并不是真的在问如何解决它(因为call1() 工作得很好)。如果有人知道为什么 Go 不能执行呼叫,我会问一个更深层次的问题。 “所以我的问题不在于为什么我的代码会产生这个问题——我真正的问题是:为什么在第二种情况下 Go 不能执行函数调用?”我问是因为xCopy 下面仍然是一个字符串。
    • 也许我只是过度假设了反射的能力......
    • 我回答的第一段解释了为什么 call2 不起作用。我将删除代码以使其更清晰。
    猜你喜欢
    • 2017-07-13
    • 1970-01-01
    • 2019-01-06
    • 2020-03-03
    • 1970-01-01
    • 2014-06-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多