From 391813c2602a7e1be2c5d65bccab7ae9ef76d180 Mon Sep 17 00:00:00 2001 From: Vasiliy Tolstov Date: Sat, 4 May 2024 14:34:41 +0300 Subject: [PATCH] util/reflect: add StructFieldNameByTag Signed-off-by: Vasiliy Tolstov --- util/reflect/struct.go | 42 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 42 insertions(+) diff --git a/util/reflect/struct.go b/util/reflect/struct.go index cfa136ff..09132b08 100644 --- a/util/reflect/struct.go +++ b/util/reflect/struct.go @@ -25,6 +25,48 @@ type StructField struct { Field reflect.StructField } +// StructFieldNameByTag get struct field name by tag key and its value +func StructFieldNameByTag(src interface{}, tkey string, tval string) (string, error) { + sv := reflect.ValueOf(src) + if sv.Kind() == reflect.Ptr { + sv = sv.Elem() + } + if sv.Kind() != reflect.Struct { + return "", ErrInvalidStruct + } + + typ := sv.Type() + for idx := 0; idx < typ.NumField(); idx++ { + fld := typ.Field(idx) + val := sv.Field(idx) + if len(fld.PkgPath) != 0 { + continue + } + + if ts, ok := fld.Tag.Lookup(tkey); ok { + for _, p := range strings.Split(ts, ",") { + if p == tval { + return fld.Name, nil + } + } + } + + switch val.Kind() { + case reflect.Ptr: + if val = val.Elem(); val.Kind() == reflect.Struct { + if name, err := StructFieldNameByTag(val.Interface(), tkey, tval); err == nil { + return name, nil + } + } + case reflect.Struct: + if name, err := StructFieldNameByTag(val.Interface(), tkey, tval); err == nil { + return name, nil + } + } + } + return "", ErrNotFound +} + // StructFieldByTag get struct field by tag key and its value func StructFieldByTag(src interface{}, tkey string, tval string) (interface{}, error) { sv := reflect.ValueOf(src)