Zouglou
Zouglou

Reputation: 129

Call a struct field with a string in golang

I want to call a field of my structure with a string, so I checked out and I saw that I need to use the reflection package. Here's my code:

package main

import (
    "fmt"
    "reflect"
)


type cmd struct{
    echo func() (string,error)
}



func main() {
    cmd:=cmd{
        echo : func () (string,error){
            return "test", nil
        },
    }
    fmt.Println(reflect.ValueOf(&cmd).MethodByName("echo").Call([]reflect.Value{}))

}

And when I want to build it, it panics like :

panic: reflect: call of reflect.Value.Call on zero Value

goroutine 1 [running]:
reflect.flag.mustBe(...)
        c:/go/src/reflect/value.go:208
reflect.Value.Call(0x0, 0x0, 0x0, 0xc0000c7f50, 0x0, 0x0, 0x0, 0x0, 0xc000086058)
        c:/go/src/reflect/value.go:319 +0x174

I do not understand the []reflect.Value{}, why do I need to use this on the line :

reflect.ValueOf(&cmd).MethodByName("echo").Call([]reflect.Value{})

Hope someone can help ! :D

Chris

Upvotes: 1

Views: 2091

Answers (1)

icza
icza

Reputation: 417552

cmd.echo is not a method. It's a field of function type. Access it using Value.FieldByName().

And only exported fields can be accessed, rename it to Echo.

And you have to pass a non-pointer cmd, or if you pass &cmd, you have to call Value.Elem().

Working example:

type cmd struct {
    Echo func() (string, error)
}

cmd := cmd{
    Echo: func() (string, error) {
        return "test", nil
    },
}
fmt.Println(reflect.ValueOf(cmd).FieldByName("Echo").Call([]reflect.Value{}))

This outputs (try it on the Go Playground):

[test <error Value>]

Also note that if the function does not have parameters, you pass nil to Value.Call():

reflect.ValueOf(cmd).FieldByName("Echo").Call(nil)

Upvotes: 3

Related Questions