diff --git a/copier.go b/copier.go index 386e388..a308656 100644 --- a/copier.go +++ b/copier.go @@ -61,8 +61,7 @@ func Copy(toValue interface{}, fromValue interface{}) (err error) { dest = to } - for i := 0; i < fromType.NumField(); i++ { - field := fromType.Field(i) + for _, field := range deepFields(fromType) { if !field.Anonymous { name := field.Name fromField := source.FieldByName(name) @@ -104,3 +103,18 @@ func Copy(toValue interface{}, fromValue interface{}) (err error) { } return } + +func deepFields(ifaceType reflect.Type) []reflect.StructField { + var fields []reflect.StructField + + for i := 0; i < ifaceType.NumField(); i++ { + v := ifaceType.Field(i) + if v.Anonymous && v.Type.Kind() == reflect.Struct { + fields = append(fields, deepFields(v.Type)...) + } else { + fields = append(fields, v) + } + } + + return fields +} diff --git a/copier_test.go b/copier_test.go index b085d25..4f5882c 100644 --- a/copier_test.go +++ b/copier_test.go @@ -23,17 +23,43 @@ func (user *User) DoubleAge() int32 { type Employee struct { Name string Age int32 - EmployeId int64 + EmployeID int64 DoubleAge int32 SuperRule string Notes []string flags []byte } +type Base struct { + BaseField1 int + BaseField2 int +} + +type HaveEmbed struct { + EmbedField1 int + EmbedField2 int + Base +} + func (employee *Employee) Role(role string) { employee.SuperRule = "Super " + role } +func TestEmbedded(t *testing.T) { + base := Base{} + embeded := HaveEmbed{} + embeded.BaseField1 = 1 + embeded.BaseField2 = 2 + embeded.EmbedField1 = 3 + embeded.EmbedField2 = 4 + + Copy(&base, &embeded) + + if base.BaseField1 != 1 { + t.Error("Embedded fields not copied") + } +} + func TestCopyStruct(t *testing.T) { user := User{Name: "Jinzhu", Age: 18, Role: "Admin", Notes: []string{"hello world"}, flags: []byte{'x'}} employee := Employee{}