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

25,998

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.

Share:
25,998
anindyaju99
Author by

anindyaju99

Updated on July 09, 2022

Comments

  • anindyaju99
    anindyaju99 almost 2 years

    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.

  • anindyaju99
    anindyaju99 about 7 years
    Yes realized that after looking at stackoverflow.com/questions/14116840/… Trying to find a way to mark my question as duplicate of that one without down-voting myself :D
  • Ayman Hussain
    Ayman Hussain almost 5 years
    In my in case the interface was not a pointer. Changing it to pointer resolved it.