Как через fieldName структуры получить значение - PullRequest
0 голосов
/ 15 апреля 2019
type mcat struct {
    ID int
}
type cat struct {
    Name string
    M    mcat
}

func getValue(path string, mcat cat){
    //throuth struct path get the value
}

func main(){
    mycat := cat{"cat", mcat{1}}
    id := getvalue("/M/ID", mycat)
}

Могу ли я сделать это, подумав, чтобы получить значение на основе имени поля?

1 Ответ

0 голосов
/ 15 апреля 2019

Вы можете делать, что хотите, с помощью функции Value.FieldByName().Просто диапазон по частям пути, которые могут быть разделены, используя strings.Split().

Вот пример:

func getValue(i interface{}, path string) interface{} {
    v := reflect.ValueOf(i)
    for _, field := range strings.Split(path[1:], "/") {
        v = v.FieldByName(field)
    }
    return v.Interface()
}

func main() {
    mycat := cat{"cat", mcat{1}}
    id := getValue(mycat, "/M/ID")
    fmt.Println(id)
}

Он выводит (попробуйте на Go Playground ):

1

Некоторые замечания:

Приведенное выше решение работает для всех типов структур, а не только с cat,Проверяет, является ли переданное значение структурой или поле существует.

Я вырезал начальный / пути с помощью выражения среза: path[1:], поэтому нам не нужно иметь дело спустое имя поля внутри цикла.

Приведенный выше getValue() возвращает результат в виде interface{}.Если вам нужно ID как int, вы можете использовать утверждение типа следующим образом:

var intID int
intID = id.(int)

Также обратите внимание, что может быть лучше / полезнее использовать переменный параметр для пути:

func getValue(i interface{}, path ...string) interface{} {
    v := reflect.ValueOf(i)
    for _, field := range path {
        v = v.FieldByName(field)
    }
    return v.Interface()
}

func main() {
    mycat := cat{"cat", mcat{1}}
    id := getValue(mycat, "M", "ID")
    fmt.Println(id)
}

Вывод одинаковый.Попробуйте это на Go Playground .

...