diff --git a/merge.go b/merge.go index 1f689db..5606180 100644 --- a/merge.go +++ b/merge.go @@ -219,20 +219,6 @@ func deepMerge(dstIn, src reflect.Value, visited map[uintptr]*visit, depth int, break } - if dst.Kind() != reflect.Ptr && src.Type().AssignableTo(dst.Type()) { - if dst.IsNil() || overwrite { - if overwrite || isEmptyValue(dst) { - if dst.CanSet() { - dst.Set(src) - } else { - dst = src - } - } - } - - break - } - if src.Kind() != reflect.Interface { if dst.IsNil() || (src.Kind() != reflect.Ptr && overwrite) { if dst.CanSet() && (overwrite || isEmptyValue(dst)) { @@ -263,8 +249,28 @@ func deepMerge(dstIn, src reflect.Value, visited map[uintptr]*visit, depth int, dst = src } } - } else if _, err = deepMerge(dst.Elem(), src.Elem(), visited, depth+1, config); err != nil { - return + break + } + + if dst.Elem().Kind() == src.Elem().Kind() { + if dst, err = deepMerge(dst.Elem(), src.Elem(), visited, depth+1, config); err != nil { + return + } + break + } + + if dst.Kind() != reflect.Ptr && src.Type().AssignableTo(dst.Type()) { + if dst.IsNil() || overwrite { + if overwrite || isEmptyValue(dst) { + if dst.CanSet() { + dst.Set(src) + } else { + dst = src + } + } + } + + break } default: mustSet := (!isEmptyValue(src) || overwriteWithEmptySrc) && (overwrite || isEmptyValue(dst)) diff --git a/merge_interface_concrete_test.go b/merge_interface_concrete_test.go index 9b5e82a..510177c 100644 --- a/merge_interface_concrete_test.go +++ b/merge_interface_concrete_test.go @@ -40,3 +40,37 @@ func TestMergeInterfaceWithDifferentConcreteTypes(t *testing.T) { t.Errorf("Handler not merged in properly: got %q header value %q, want %q", "Test", got, want) } } + +func TestMergeInterfaceWithSameConcreteTypes(t *testing.T) { + type testStruct struct { + Name string + Value string + } + type interfaceStruct struct { + Field interface{} + } + dst := interfaceStruct{ + Field: testStruct{ + Value: "keepMe", + }, + } + + src := interfaceStruct{ + Field: testStruct{ + Name: t.Name(), + }, + } + + if err := Merge(&dst, src); err != nil { + t.Errorf("Error while merging %s", err) + } + + dstData := dst.Field.(testStruct) + srcData := src.Field.(testStruct) + if dstData.Name != srcData.Name { + t.Errorf("dst name was not updated: got %s, want %s", dstData.Name, srcData.Name) + } + if dstData.Value != "keepMe" { + t.Errorf("dst value was not preserved: got %s, want %s", dstData.Value, "keepMe") + } +}