Reflection – method call panics with "call of reflect.Value.Elem on struct Value"

huangapple go评论83阅读模式
英文:

Reflection - method call panics with "call of reflect.Value.Elem on struct Value"

问题

以下是代码段的翻译:

type Gateway struct {
    Svc1 svc1.Interface
    Svc2 svc2.Interface
}

func (g *Gateway) GetClient(service string) interface{} {
    ps := reflect.ValueOf(g)
    s := ps.Elem()
    f := s.FieldByName(strings.Title(service))
    return f.Interface()
}

func (g *Gateway) Invoke(service string, endpoint string, args... 
    interface{}) []reflect.Value {
    log.Info("Gateway.Invoke " + service + "." + endpoint)
    inputs := make([]reflect.Value, len(args))
    for i, _ := range args {
        inputs[i] = reflect.ValueOf(args[i])
    }

    client := g.GetClient(service)

    return reflect.ValueOf(client).Elem().MethodByName(endpoint).Call(inputs)
}

GetClient("svc1") 的调用正常工作

然而当我调用 Invoke("svc1", "endpoint1", someArg) 它会抛出 panic 错误

reflect: call of reflect.Value.Elem on struct Value

reflect.ValueOf(client).MethodByName(endpoint).Call(inputs) 抛出 panic 错误提示在零值上调用 Call 方法
英文:

Here is a code snippet -

type Gateway struct {
    Svc1 svc1.Interface
    Svc2 svc2.Interface
}

func (g *Gateway) GetClient(service string) interface{} {
    ps := reflect.ValueOf(g)
    s := ps.Elem()
    f := s.FieldByName(strings.Title(service))
    return f.Interface()
}

func (g *Gateway) Invoke(service string, endpoint string, args... 
    interface{}) []reflect.Value {
    log.Info("Gateway.Invoke " + service + "." + endpoint)
	inputs := make([]reflect.Value, len(args))
    for i, _ := range args {
	    inputs[i] = reflect.ValueOf(args[i])
    }

    client := g.GetClient(service)

    return reflect.ValueOf(client).Elem().MethodByName(endpoint).Call(inputs)
}

GetClient("svc1") works fine.

However, when I call Invoke("svc1", "endpoint1", someArg), it panics saying -

reflect: call of reflect.Value.Elem on struct Value

reflect.ValueOf(client).MethodByName(endpoint).Call(inputs) panics saying Call on a zero value.

答案1

得分: 11

有几个问题:

  1. 如果svc1.Interface不是指针或接口类型,reflect.Value.Elem()会引发恐慌(参见https://golang.org/pkg/reflect/#Value.Elem)。

  2. 如果Invokeendpoint参数字符串与目标方法的大小写不匹配,将会因为零值(invalid reflect.Value)而引发恐慌。请注意,您想要调用的方法必须是公开的。

英文:

There are a couple issues:

  1. If svc1.Interface is not a pointer or an interface, reflect.Value.Elem() will panic (see https://golang.org/pkg/reflect/#Value.Elem)

  2. If the endpoint argument string of Invoke doesn't match the capitalization of the target method, it will panic due to zero value (invalid reflect.Value). Please note that the method you want to call must be exported.

huangapple
  • 本文由 发表于 2017年6月15日 19:25:33
  • 转载请务必保留本文链接:https://go.coder-hub.com/44566293.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定