Skip to content

Commit

Permalink
Merge pull request #49 from swordqiu/hotfix/qj-find-anoymous-struct-r…
Browse files Browse the repository at this point in the history
…ecode

fix: FindAnonymousStructPoint recode
  • Loading branch information
yunion-ci-robot committed Feb 21, 2020
2 parents 27c6f82 + bd50c24 commit f129027
Show file tree
Hide file tree
Showing 2 changed files with 71 additions and 6 deletions.
25 changes: 19 additions & 6 deletions util/reflectutils/reflectutils.go
Original file line number Diff line number Diff line change
Expand Up @@ -160,12 +160,11 @@ func ExpandInterface(val interface{}) []interface{} {
// tagetType must not be a pointer
func getAnonymouStructPointer(structValue reflect.Value, targetType reflect.Type) interface{} {
structType := structValue.Type()
if structType == targetType {
return structValue.Addr().Interface()
}
for i := 0; i < structValue.NumField(); i += 1 {
fieldType := structType.Field(i)
if fieldType.Type == targetType {
val := structValue.Field(i) // val is not a pointer
return val.Addr().Interface()
}
if fieldType.Anonymous && fieldType.Type.Kind() == reflect.Struct {
ptr := getAnonymouStructPointer(structValue.Field(i), targetType)
if ptr != nil {
Expand All @@ -177,12 +176,26 @@ func getAnonymouStructPointer(structValue reflect.Value, targetType reflect.Type
}

func FindAnonymouStructPointer(data interface{}, targetPtr interface{}) error {
targetValue := reflect.ValueOf(targetPtr).Elem()
targetValue := reflect.ValueOf(targetPtr)
if targetValue.Kind() != reflect.Ptr {
return fmt.Errorf("target must be a pointer to pointer")
}
targetValue = targetValue.Elem()
if targetValue.Kind() != reflect.Ptr {
return fmt.Errorf("target must be a pointer to pointer")
}
targetType := targetValue.Type().Elem()
structValue := reflect.Indirect(reflect.ValueOf(data))
if targetType.Kind() != reflect.Struct {
return fmt.Errorf("target type must be a struct")
}
structValue := reflect.ValueOf(data)
if structValue.Kind() != reflect.Ptr {
return fmt.Errorf("data type must be a pointer to struct")
}
structValue = reflect.ValueOf(data).Elem()
if structValue.Kind() != reflect.Struct {
return fmt.Errorf("data type must be a pointer to struct")
}
ptr := getAnonymouStructPointer(structValue, targetType)
if ptr == nil {
return fmt.Errorf("no anonymous struct found")
Expand Down
52 changes: 52 additions & 0 deletions util/reflectutils/reflectutils_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -93,3 +93,55 @@ func TestSetStructFieldValue(t *testing.T) {
t.Errorf("Fail to find struct field")
}
}

func TestFindAnonymouStructPointer(t *testing.T) {
type Struct1 struct {
Name1 string
}
type Struct2 struct {
Name2 string
Struct1
}
type Struct3 struct {
Name3 string
Struct2
}

s3 := Struct3{}
var t3 *Struct3
var t2 *Struct2
var t1 *Struct1

err := FindAnonymouStructPointer(&s3, t3)
if err == nil {
t.Errorf("t3 is not a pointer to pointer, shoud fail")
}
err = FindAnonymouStructPointer(s3, &t3)
if err == nil {
t.Errorf("s3 is not pointer, should fail")
}

err = FindAnonymouStructPointer(&s3, &t3)
if err != nil {
t.Errorf("Fail to find Struct3 in Struct3")
}
if t3 != &s3 {
t.Errorf("t3 != &s3")
}

err = FindAnonymouStructPointer(&s3, &t2)
if err != nil {
t.Errorf("Fail to find Struct2 in Struct3")
}
if t2 != &s3.Struct2 {
t.Errorf("t2 != &s3.Struct2")
}

err = FindAnonymouStructPointer(&s3, &t1)
if err != nil {
t.Errorf("Fail to find Struct1 in Struct3")
}
if t1 != &s3.Struct1 {
t.Errorf("t1 != &s3.Struct1")
}
}

0 comments on commit f129027

Please sign in to comment.