用反射调用struct方法 [英] Calling struct method with reflection

查看:60
本文介绍了用反射调用struct方法的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在递归反射函数中调用方法时遇到麻烦.在这里:

I'm having trouble calling a method in my recursive reflection function. Here it is:

func setPropertiesFromFlags(v reflect.Value, viper *viper.Viper) {
    t := v.Type()
    method := v.MethodByName("Parse")
    fmt.Println(method)
    for i := 0; i < t.NumField(); i++ {
        field := t.Field(i)
        switch field.Type.Kind() {
        case reflect.Struct:
            setPropertiesFromFlags(v.Field(i), viper)
        case reflect.String:
            v.Field(i).SetString(viper.GetString(field.Tag.Get("name")))
    }
}

我正在使用以下函数调用该函数:

I'm calling the function with:

// Config struct passed to all services
type Config struct {
    common.Config
    common.ServerConfig
    common.AuthConfig
}
// Parse the thing already!
func (c *Config) Parse() {
    fmt.Println("RUN THIS THING")
}
int main() {
   setPropertiesFromFlags(reflect.ValueOf(c).Elem(), viper)
}

我希望的是将我的parse方法放到我正在打印方法的地方,然后对它运行.Call().相反,它正在打印:我无法调用的<无效的reflect.Value> .

What I'm hoping for is to get my parse method in the place where I'm printing method and run .Call() against it. Instead it's printing out: <invalid reflect.Value> which I cannot call against.

我想我无法将每个方法的返回值都放在头上.我知道我必须使用ValueOf来提取值,但是似乎我尝试从反射类本身获取方法的任何排列:-p sigh

I suppose I'm having trouble wrapping my head around the return values of each method. I know I have to use ValueOf to pull the value but it seems any permutation I try I'm getting the methods from the reflection class itself :-p sigh

推荐答案

问题是该方法在指针接收器上,但是该函数在赋值器接收器上工作.重写该函数以使用指向结构的指针:

The problem is that the method is on the pointer receiver, but the function is working with a valuer receiver. Rewrite the function to work with a pointer to a struct:

func setPropertiesFromFlags(vp reflect.Value, viper *viper.Viper) {
    method := vp.MethodByName("Parse")
    fmt.Println(method)

    v := vp.Elem()
    t := v.Type()
    for i := 0; i < t.NumField(); i++ {
        field := t.Field(i)
        switch field.Type.Kind() {
        case reflect.Struct:
            setPropertiesFromFlags(v.Field(i).Addr(), viper) // <-- take address of field here
        case reflect.String:
            v.Field(i).SetString(viper.GetString(field.Tag.Get("name")))
        }
    }
}

像这样打电话:

   setPropertiesFromFlags(reflect.ValueOf(c), viper) // <-- do not call Elem()

这篇关于用反射调用struct方法的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆