From 67d9ddd8b517896db8222e4ac398b6d7ccc36289 Mon Sep 17 00:00:00 2001 From: zed Date: Tue, 23 Apr 2024 17:58:07 +0800 Subject: [PATCH] feat: Copy to Nil pointer of struct --- copier.go | 12 +++++++++++- copier_test.go | 18 ++++++++++++++++++ 2 files changed, 29 insertions(+), 1 deletion(-) diff --git a/copier.go b/copier.go index 0cc6465..3550769 100644 --- a/copier.go +++ b/copier.go @@ -122,7 +122,7 @@ func copier(toValue interface{}, fromValue interface{}, opt Option) (err error) isSlice bool amount = 1 from = indirect(reflect.ValueOf(fromValue)) - to = indirect(reflect.ValueOf(toValue)) + to = indirectAndFill(reflect.ValueOf(toValue)) converters = opt.converters() mappings = opt.fieldNameMapping() ) @@ -544,6 +544,16 @@ func deepFields(reflectType reflect.Type) []reflect.StructField { return res } +func indirectAndFill(reflectValue reflect.Value) reflect.Value { + for reflectValue.Kind() == reflect.Ptr { + if reflectValue.IsNil() { + reflectValue.Set(reflect.New(reflectValue.Type().Elem())) + } + reflectValue = reflectValue.Elem() + } + return reflectValue +} + func indirect(reflectValue reflect.Value) reflect.Value { for reflectValue.Kind() == reflect.Ptr { reflectValue = reflectValue.Elem() diff --git a/copier_test.go b/copier_test.go index 4769eba..f510370 100644 --- a/copier_test.go +++ b/copier_test.go @@ -1762,3 +1762,21 @@ func TestNestedNilPointerStruct(t *testing.T) { t.Errorf("to (%v) value should equal from (%v) value", to.Title, from.Title) } } + +func TestCopyToNilPointerOfStruct(t *testing.T) { + type struct1 struct { + A int + } + type struct2 struct { + A int + } + s1 := struct1{A: 1} + var s2 *struct2 + err := copier.Copy(&s2, s1) + if err != nil { + t.Error("should not error") + } + if s1.A != (*s2).A { + t.Error("should equal") + } +}