mirror of
https://github.com/c9s/bbgo.git
synced 2024-11-10 09:11:55 +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
|
||||
}
|
||||
|
||||
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 {
|
||||
sv := reflect.ValueOf(obj)
|
||||
st := reflect.TypeOf(obj)
|
||||
|
@ -82,11 +86,19 @@ func IterateFieldsByTag(obj interface{}, tagName string, cb StructFieldIterator)
|
|||
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)
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
|
||||
// call the iterator
|
||||
if err := cb(tag, ft, fv); err != nil {
|
||||
return err
|
||||
}
|
||||
|
|
|
@ -40,5 +40,64 @@ func TestIterateFields(t *testing.T) {
|
|||
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