From 38cb3f3675755b3a045e45d9808df81b404bde05 Mon Sep 17 00:00:00 2001 From: chengjin Date: Thu, 4 Jun 2020 21:24:00 +0800 Subject: [PATCH 1/5] fix bug; code optimization --- defaults.go | 15 +++++++-------- defaults_test.go | 17 +++++++++++++++++ 2 files changed, 24 insertions(+), 8 deletions(-) diff --git a/defaults.go b/defaults.go index 3f77fd5..ffca9be 100644 --- a/defaults.go +++ b/defaults.go @@ -133,13 +133,11 @@ func setField(field reflect.Value, defaultVal string) error { } field.Set(ref.Elem().Convert(field.Type())) case reflect.Struct: - ref := reflect.New(field.Type()) if defaultVal != "" && defaultVal != "{}" { - if err := json.Unmarshal([]byte(defaultVal), ref.Interface()); err != nil { + if err := json.Unmarshal([]byte(defaultVal), field.Addr().Interface()); err != nil { return err } } - field.Set(ref.Elem()) case reflect.Ptr: field.Set(reflect.New(field.Type().Elem())) } @@ -150,13 +148,10 @@ func setField(field reflect.Value, defaultVal string) error { setField(field.Elem(), defaultVal) callSetter(field.Interface()) case reflect.Struct: - ref := reflect.New(field.Type()) - ref.Elem().Set(field) - if err := Set(ref.Interface()); err != nil { + if err := Set(field.Addr().Interface()); err != nil { return err } - callSetter(ref.Interface()) - field.Set(ref.Elem()) + callSetter(field.Addr().Interface()) case reflect.Slice: for j := 0; j < field.Len(); j++ { if err := setField(field.Index(j), defaultVal); err != nil { @@ -176,6 +171,10 @@ func shouldInitializeField(field reflect.Value, tag string) bool { switch field.Kind() { case reflect.Struct: return true + case reflect.Ptr: + if field.Interface() != nil && field.Elem().Kind() == reflect.Struct { + return true + } case reflect.Slice: return field.Len() > 0 || tag != "" } diff --git a/defaults_test.go b/defaults_test.go index b04ca6b..a41652d 100644 --- a/defaults_test.go +++ b/defaults_test.go @@ -389,3 +389,20 @@ func TestCanUpdate(t *testing.T) { } } } + +type Child struct { + Name string `default:"Tom"` + Age int `default:"20"` +} + +type Parent struct { + Child *Child +} + +func TestPointerStructMember(t *testing.T) { + m := Parent{Child: &Child{Name: "Jim"}} + Set(&m) + if m.Child.Age != 20 { + t.Errorf("20 is expected") + } +} From b76a8acf3eec2c2a73d3b5ad8642f6442660e8a3 Mon Sep 17 00:00:00 2001 From: chengjin Date: Thu, 4 Jun 2020 21:29:04 +0800 Subject: [PATCH 2/5] go.mod --- go.mod | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 go.mod diff --git a/go.mod b/go.mod new file mode 100644 index 0000000..4f06bae --- /dev/null +++ b/go.mod @@ -0,0 +1,3 @@ +module github.com/creasty/defaults + +go 1.11 From be9cf53744ce93afa8b09694c9539967d9580448 Mon Sep 17 00:00:00 2001 From: chengjin Date: Thu, 4 Jun 2020 21:37:34 +0800 Subject: [PATCH 3/5] fix issue #16 --- defaults.go | 2 +- defaults_test.go | 32 ++++++++++++++++++++++++++++++++ 2 files changed, 33 insertions(+), 1 deletion(-) diff --git a/defaults.go b/defaults.go index ffca9be..cbe3fc3 100644 --- a/defaults.go +++ b/defaults.go @@ -38,7 +38,7 @@ func Set(ptr interface{}) error { } } } - + callSetter(ptr) return nil } diff --git a/defaults_test.go b/defaults_test.go index a41652d..ec20c65 100644 --- a/defaults_test.go +++ b/defaults_test.go @@ -406,3 +406,35 @@ func TestPointerStructMember(t *testing.T) { t.Errorf("20 is expected") } } + +type Main struct { + MainInt int `default:"-"` + *Other `default:"{}"` +} + +type Other struct { + OtherInt int `default:"-"` +} + +func (s *Main) SetDefaults() { + if CanUpdate(s.MainInt) { + s.MainInt = 1 + } +} + +func (s *Other) SetDefaults() { + if CanUpdate(s.OtherInt) { + s.OtherInt = 1 + } +} + +func TestDefaultsSetter(t *testing.T) { + main := &Main{} + Set(main) + if main.OtherInt != 1 { + t.Errorf("expected 1 for OtherInt, got %d", main.OtherInt) + } + if main.MainInt != 1 { + t.Errorf("expected 1 for MainInt, got %d", main.MainInt) + } +} From 83cc2373a8a5c57e24d2fb35951130cf84793b9d Mon Sep 17 00:00:00 2001 From: chengjin Date: Fri, 5 Jun 2020 09:29:58 +0800 Subject: [PATCH 4/5] handle nil --- defaults.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/defaults.go b/defaults.go index cbe3fc3..8fba889 100644 --- a/defaults.go +++ b/defaults.go @@ -172,14 +172,14 @@ func shouldInitializeField(field reflect.Value, tag string) bool { case reflect.Struct: return true case reflect.Ptr: - if field.Interface() != nil && field.Elem().Kind() == reflect.Struct { + if !field.IsNil() && field.Elem().Kind() == reflect.Struct { return true } case reflect.Slice: return field.Len() > 0 || tag != "" } - return (tag != "") + return tag != "" } // CanUpdate returns true when the given value is an initial value of its type From 39b28d317a24c2c9a59e53a96944a0272c6eeb81 Mon Sep 17 00:00:00 2001 From: chengjin Date: Tue, 9 Jun 2020 10:42:53 +0800 Subject: [PATCH 5/5] remove a redundant call of callSetter --- defaults.go | 1 - 1 file changed, 1 deletion(-) diff --git a/defaults.go b/defaults.go index 8fba889..bdb0e9a 100644 --- a/defaults.go +++ b/defaults.go @@ -151,7 +151,6 @@ func setField(field reflect.Value, defaultVal string) error { if err := Set(field.Addr().Interface()); err != nil { return err } - callSetter(field.Addr().Interface()) case reflect.Slice: for j := 0; j < field.Len(); j++ { if err := setField(field.Index(j), defaultVal); err != nil {