Skip to content

Commit

Permalink
Merge pull request #18 from sdghchj/master
Browse files Browse the repository at this point in the history
set default values of fields of a pointer type field
  • Loading branch information
creasty authored Jun 9, 2020
2 parents c58e679 + 39b28d3 commit 0dea786
Show file tree
Hide file tree
Showing 3 changed files with 60 additions and 10 deletions.
18 changes: 8 additions & 10 deletions defaults.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ func Set(ptr interface{}) error {
}
}
}

callSetter(ptr)
return nil
}

Expand Down Expand Up @@ -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()))
}
Expand All @@ -150,13 +148,9 @@ 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())
case reflect.Slice:
for j := 0; j < field.Len(); j++ {
if err := setField(field.Index(j), defaultVal); err != nil {
Expand All @@ -176,11 +170,15 @@ func shouldInitializeField(field reflect.Value, tag string) bool {
switch field.Kind() {
case reflect.Struct:
return true
case reflect.Ptr:
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
Expand Down
49 changes: 49 additions & 0 deletions defaults_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -389,3 +389,52 @@ 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")
}
}

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)
}
}
3 changes: 3 additions & 0 deletions go.mod
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
module github.com/creasty/defaults

go 1.11

0 comments on commit 0dea786

Please sign in to comment.