Something went wrong on our end
-
Volker Schukai authoredVolker Schukai authored
get.go 1.17 KiB
// Copyright 2022 schukai GmbH
// SPDX-License-Identifier: AGPL-3.0
package pathfinder
import (
"reflect"
"strconv"
"strings"
)
// This function returns the value of a field in a struct, given a path to the field.
func GetValue[D any](obj D, keyWithDots string) (any, error) {
keySlice := strings.Split(keyWithDots, ".")
v := reflect.ValueOf(obj)
for _, key := range keySlice[0:len(keySlice)] {
switch v.Kind() {
case reflect.Ptr, reflect.Slice, reflect.Array, reflect.Interface:
v = v.Elem()
}
switch v.Kind() {
case reflect.Map:
v = v.MapIndex(reflect.ValueOf(key))
if !v.IsValid() {
return nil, newInvalidPathError(keyWithDots)
}
case reflect.Slice, reflect.Array:
index, err := strconv.Atoi(key)
if err != nil {
return nil, newInvalidPathError(keyWithDots)
}
v = v.Index(index)
case reflect.Struct:
v = v.FieldByName(key)
if !v.IsValid() {
return nil, newInvalidPathError(keyWithDots)
}
default:
return nil, newInvalidPathError(keyWithDots)
}
}
if v.Kind() == reflect.Invalid {
return nil, newInvalidPathError(keyWithDots)
}
for v.Kind() == reflect.Ptr {
v = v.Elem()
}
return v.Interface(), nil
}