Last active
June 27, 2022 10:59
-
-
Save GerardRodes/6a0a2c9f22fd80fcfe66f776bbfb3be4 to your computer and use it in GitHub Desktop.
Go - get field value by tag value
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package main | |
import ( | |
"errors" | |
"reflect" | |
) | |
func GetFieldValueByTagValue[T any](instance any, tagname, tagvalue string) (T, error) { | |
var noop T | |
if tagname == "" { | |
return noop, errors.New("tagname cannot be empty") | |
} | |
if tagvalue == "" { | |
return noop, errors.New("tagvalue cannot be empty") | |
} | |
v := reflect.TypeOf(instance) | |
for i := 0; i < v.NumField(); i++ { | |
iField := reflect.ValueOf(instance).Field(i).Interface() | |
if v.Field(i).Tag.Get(tagname) == tagvalue { | |
if v, ok := iField.(T); ok { | |
return v, nil | |
} | |
} else if v.Field(i).Type.Kind() == reflect.Struct { | |
v, err := GetFieldValueByTagValue[T](iField, tagname, tagvalue) | |
if err == nil { | |
return v, nil | |
} | |
} | |
} | |
return noop, errors.New("not found") | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package main | |
import ( | |
"testing" | |
"github.com/stretchr/testify/assert" | |
) | |
func TestGetFieldValueByTagValue(t *testing.T) { | |
type Embedded struct { | |
Field string `foo:"Embedded.Field"` | |
} | |
type Nested struct { | |
Field string `foo:"Nested.Field"` | |
} | |
type Base struct { | |
Field string `foo:"Base.Field"` | |
Nested Nested `foo:"Base.Nested"` | |
Embedded `foo:"Base.Embedded"` | |
} | |
a := Base{ | |
Field: "Base.Field value", | |
Nested: Nested{"Nested.Field value"}, | |
Embedded: Embedded{"Embedded.Field value"}, | |
} | |
t.Run("get string", func(t *testing.T) { | |
v, err := GetFieldValueByTagValue[string](a, "foo", "Base.Field") | |
assert.NoError(t, err) | |
assert.Equal(t, v, "Base.Field value") | |
}) | |
t.Run("get custom type", func(t *testing.T) { | |
v, err := GetFieldValueByTagValue[Nested](a, "foo", "Base.Nested") | |
assert.NoError(t, err) | |
assert.Equal(t, v, Nested{"Nested.Field value"}) | |
}) | |
t.Run("get nested field", func(t *testing.T) { | |
v, err := GetFieldValueByTagValue[string](a, "foo", "Nested.Field") | |
assert.NoError(t, err) | |
assert.Equal(t, v, "Nested.Field value") | |
}) | |
t.Run("get embedded", func(t *testing.T) { | |
v, err := GetFieldValueByTagValue[Embedded](a, "foo", "Base.Embedded") | |
assert.NoError(t, err) | |
assert.Equal(t, v, Embedded{"Embedded.Field value"}) | |
}) | |
t.Run("get embedded field", func(t *testing.T) { | |
v, err := GetFieldValueByTagValue[string](a, "foo", "Embedded.Field") | |
assert.NoError(t, err) | |
assert.Equal(t, v, "Embedded.Field value") | |
}) | |
t.Run("not found", func(t *testing.T) { | |
_, err := GetFieldValueByTagValue[string](a, "zzz", "zzz") | |
assert.EqualError(t, err, "not found") | |
_, err = GetFieldValueByTagValue[string](a, "foo", "zzz") | |
assert.EqualError(t, err, "not found") | |
_, err = GetFieldValueByTagValue[string](a, "foo", "Base.Nested") | |
assert.EqualError(t, err, "not found") | |
}) | |
t.Run("tagname empty", func(t *testing.T) { | |
_, err := GetFieldValueByTagValue[string](a, "", "zzz") | |
assert.EqualError(t, err, "tagname cannot be empty") | |
}) | |
t.Run("tagvalue empty", func(t *testing.T) { | |
_, err := GetFieldValueByTagValue[string](a, "zzz", "") | |
assert.EqualError(t, err, "tagvalue cannot be empty") | |
}) | |
t.Run("type not matching", func(t *testing.T) { | |
_, err := GetFieldValueByTagValue[int](a, "foo", "Base.Field") | |
assert.EqualError(t, err, "not found") | |
}) | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment