feat: add.

This commit is contained in:
tx7do
2023-11-06 14:11:20 +08:00
parent 83bb818ade
commit da82d442cc
20 changed files with 545 additions and 94 deletions

37
structutil/structutils.go Normal file
View File

@@ -0,0 +1,37 @@
package structutil
import "reflect"
// ForEach given a struct, calls the passed in function with each visible struct field's name, value and tag.
func ForEach[T any](structInstance T, function func(key string, value any, tag reflect.StructTag)) {
typeOf := reflect.TypeOf(structInstance)
valueOf := reflect.ValueOf(structInstance)
fields := reflect.VisibleFields(typeOf)
for _, field := range fields {
value := valueOf.FieldByName(field.Name)
function(field.Name, value.Interface(), field.Tag)
}
}
// ToMap given a struct, converts it to a map[string]any.
// This function also takes struct tag names as optional parameters - if passed in, the struct tags will be used to remap or omit values.
func ToMap[T any](structInstance T, structTags ...string) map[string]any {
output := make(map[string]any, 0)
ForEach(structInstance, func(key string, value any, tag reflect.StructTag) {
if tag != "" {
for _, s := range structTags {
if tagValue, isPresent := tag.Lookup(s); isPresent && tagValue != "" {
key = tagValue
break
}
}
}
if key != "-" {
output[key] = value
}
})
return output
}

View File

@@ -0,0 +1,55 @@
package structutil_test
import (
"reflect"
"testing"
"github.com/stretchr/testify/assert"
"github.com/tx7do/go-utils/structutil"
)
type TestStruct struct {
First string
Second int
Third bool `struct:"third"`
}
func TestForEach(t *testing.T) {
instance := TestStruct{
"moishe",
22,
true,
}
structutil.ForEach(instance, func(key string, value any, tag reflect.StructTag) {
switch key {
case "First":
assert.Equal(t, "moishe", value.(string))
assert.Zero(t, tag)
case "Second":
assert.Equal(t, 22, value.(int))
assert.Zero(t, tag)
case "Third":
assert.Equal(t, true, value.(bool))
assert.Equal(t, "third", tag.Get("struct"))
}
})
}
func TestToMap(t *testing.T) {
instance := TestStruct{
"moishe",
22,
true,
}
assert.Equal(t, map[string]any{
"First": "moishe",
"Second": 22,
"Third": true,
}, structutil.ToMap(instance))
assert.Equal(t, map[string]any{
"First": "moishe",
"Second": 22,
"third": true,
}, structutil.ToMap(instance, "struct"))
}