Go 用反射调用struct方法

Go 用反射调用struct方法,go,reflection,Go,Reflection,在递归反射函数中调用方法时遇到问题。这是: 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) sw

在递归反射函数中调用方法时遇到问题。这是:

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")))
    }
}
我希望在打印方法的地方得到我的parse方法,并对其运行.Call()。相反,它打印出来:
,我不能反对它


我想我很难理解每个方法的返回值。我知道我必须使用ValueOf来提取值,但我尝试的任何排列方式我都是从反射类本身获取方法:-p sign

问题是该方法位于指针接收器上,但该函数正在与valuer接收器一起工作。 重写函数以使用指向结构的指针:

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")))
        }
    }
}
func setPropertiesFromFlags(vp reflect.Value,viper*viper.viper){
方法:=vp.MethodByName(“解析”)
fmt.Println(方法)
v:=vp.Elem()
t:=v.Type()
对于i:=0;isetPropertiesFromFlags(v.Field(i).Addr(),viper)//问题在于该方法位于指针接收器上,但该函数正在使用valuer接收器。
重写函数以使用指向结构的指针:

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")))
        }
    }
}
func setPropertiesFromFlags(vp reflect.Value,viper*viper.viper){
方法:=vp.MethodByName(“解析”)
fmt.Println(方法)
v:=vp.Elem()
t:=v.Type()
对于i:=0;isetPropertiesFromFlags(v.Field(i).Addr(),viper)//我相信这是因为它是在指针上声明的,即
Parse
方法,但您正在向函数传递一个值。也就是说,要解决这个问题,请在非指针上声明
Parse
。或者传递指针,即
setPropertiesFromFlags(reflect.ValueOf(c),viper)
(不带
.Elem()
),然后当您需要在
setPropertiesFromFlags
中操作结构时,调用
Elem
。或者继续执行您正在执行的操作,但从v的“地址”检索方法,即
v.Addr().MethodByName(“解析”)
@mkopriva你在这些评论中的答案比我快,你的最后一条评论也许是最好的答案。你应该写一个实际的答案而不是评论吗?@i或者说我太懒了,你的答案已经足够好了。@d根据你是有指针还是有值来演示你能做什么和不能做什么。(更新)我相信这是因为它是在一个指针上声明的,也就是说,
Parse
方法,但是你正在向你的函数传递一个值。也就是说,要解决这个问题,在一个非指针上声明
Parse
。或者传递指针,即
setPropertiesFromFlags(reflect.ValueOf(c),viper)
(不带
.Elem()
)然后,当您需要在
setPropertiesFromFlags
调用
Elem
中操作结构时,也可以继续执行您正在执行的操作,但从v的“地址”检索方法,即
v.Addr().MethodByName(“解析”)
@mkopriva你在这些评论中的答案比我快,你的最后一条评论也许是最好的答案。你应该写一个实际的答案而不是评论吗?@i或者说我太懒了,你的答案已经足够好了。@d根据你是有指针还是有值来演示你能做什么和不能做什么。(更新)我现在明白了。我没有通过。Addr()这是主要问题。谢谢各位。我现在明白了。我没有通过。Addr()这是主要问题。谢谢各位。
   setPropertiesFromFlags(reflect.ValueOf(c), viper) // <-- do not call Elem()