Вызов метода struct с отражением - PullRequest
0 голосов
/ 06 ноября 2019

У меня проблемы с вызовом метода в моей рекурсивной функции отражения. Вот оно:

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")))
    }
}

Я вызываю функцию с помощью:

// 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)
}

Я надеюсь, что мой метод синтаксического анализа будет в том месте, где я печатаюметод и запустить .Call () против него. Вместо этого он печатает: <invalid reflect.Value>, против которого я не могу позвонить.

Полагаю, у меня возникли проблемы с оборачиванием возвращаемых значений каждого метода. Я знаю, что должен использовать ValueOf, чтобы получить значение, но, кажется, любая перестановка, я пытаюсь получить методы из самого класса отражения :-p sigh

1 Ответ

2 голосов
/ 06 ноября 2019

Проблема в том, что метод находится на получателе указателя, но функция работает с получателем оценщика. Перепишите функцию для работы с указателем на структуру:

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()
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...