Вы можете делать, что хотите, с помощью функции 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 .