mirror of
https://github.com/c9s/bbgo.git
synced 2024-11-26 08:45:16 +00:00
Merge pull request #1225 from c9s/c9s/nested-persistence
FEATURE: support nested persistence
This commit is contained in:
commit
f71fcdee23
|
@ -52,6 +52,10 @@ func IterateFields(obj interface{}, cb func(ft reflect.StructField, fv reflect.V
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func isStructPtr(tpe reflect.Type) bool {
|
||||||
|
return tpe.Kind() == reflect.Ptr && tpe.Elem().Kind() == reflect.Struct
|
||||||
|
}
|
||||||
|
|
||||||
func IterateFieldsByTag(obj interface{}, tagName string, cb StructFieldIterator) error {
|
func IterateFieldsByTag(obj interface{}, tagName string, cb StructFieldIterator) error {
|
||||||
sv := reflect.ValueOf(obj)
|
sv := reflect.ValueOf(obj)
|
||||||
st := reflect.TypeOf(obj)
|
st := reflect.TypeOf(obj)
|
||||||
|
@ -82,11 +86,19 @@ func IterateFieldsByTag(obj interface{}, tagName string, cb StructFieldIterator)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if isStructPtr(ft.Type) && !fv.IsNil() {
|
||||||
|
// recursive iterate the struct field
|
||||||
|
if err := IterateFieldsByTag(fv.Interface(), tagName, cb); err != nil {
|
||||||
|
return fmt.Errorf("unable to iterate struct fields over the type %v: %v", ft, err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
tag, ok := ft.Tag.Lookup(tagName)
|
tag, ok := ft.Tag.Lookup(tagName)
|
||||||
if !ok {
|
if !ok {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// call the iterator
|
||||||
if err := cb(tag, ft, fv); err != nil {
|
if err := cb(tag, ft, fv); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
|
@ -40,5 +40,64 @@ func TestIterateFields(t *testing.T) {
|
||||||
assert.Error(t, err)
|
assert.Error(t, err)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestIterateFieldsByTag(t *testing.T) {
|
||||||
|
t.Run("nested", func(t *testing.T) {
|
||||||
|
var a = struct {
|
||||||
|
A int `persistence:"a"`
|
||||||
|
B int `persistence:"b"`
|
||||||
|
C *struct {
|
||||||
|
D int `persistence:"d"`
|
||||||
|
E int `persistence:"e"`
|
||||||
|
}
|
||||||
|
}{
|
||||||
|
A: 1,
|
||||||
|
B: 2,
|
||||||
|
C: &struct {
|
||||||
|
D int `persistence:"d"`
|
||||||
|
E int `persistence:"e"`
|
||||||
|
}{
|
||||||
|
D: 3,
|
||||||
|
E: 4,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
collectedTags := []string{}
|
||||||
|
cnt := 0
|
||||||
|
err := IterateFieldsByTag(&a, "persistence", func(tag string, ft reflect.StructField, fv reflect.Value) error {
|
||||||
|
cnt++
|
||||||
|
collectedTags = append(collectedTags, tag)
|
||||||
|
return nil
|
||||||
|
})
|
||||||
|
assert.NoError(t, err)
|
||||||
|
assert.Equal(t, 4, cnt)
|
||||||
|
assert.Equal(t, []string{"a", "b", "d", "e"}, collectedTags)
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("nested nil", func(t *testing.T) {
|
||||||
|
var a = struct {
|
||||||
|
A int `persistence:"a"`
|
||||||
|
B int `persistence:"b"`
|
||||||
|
C *struct {
|
||||||
|
D int `persistence:"d"`
|
||||||
|
E int `persistence:"e"`
|
||||||
|
}
|
||||||
|
}{
|
||||||
|
A: 1,
|
||||||
|
B: 2,
|
||||||
|
C: nil,
|
||||||
|
}
|
||||||
|
|
||||||
|
collectedTags := []string{}
|
||||||
|
cnt := 0
|
||||||
|
err := IterateFieldsByTag(&a, "persistence", func(tag string, ft reflect.StructField, fv reflect.Value) error {
|
||||||
|
cnt++
|
||||||
|
collectedTags = append(collectedTags, tag)
|
||||||
|
return nil
|
||||||
|
})
|
||||||
|
assert.NoError(t, err)
|
||||||
|
assert.Equal(t, 2, cnt)
|
||||||
|
assert.Equal(t, []string{"a", "b"}, collectedTags)
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user