Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 15 additions & 12 deletions defaults.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,10 +33,13 @@ func Set(ptr interface{}) error {
}

for i := 0; i < t.NumField(); i++ {
if defaultVal := t.Field(i).Tag.Get(fieldName); defaultVal != "-" {
if err := setField(v.Field(i), defaultVal); err != nil {
return err
}
defaultVal, ok := t.Field(i).Tag.Lookup(fieldName)
if ok && defaultVal == "-" {
continue
}

if err := setField(v.Field(i), defaultVal, ok); err != nil {
return err
}
}
callSetter(ptr)
Expand All @@ -51,12 +54,12 @@ func MustSet(ptr interface{}) {
}
}

func setField(field reflect.Value, defaultVal string) error {
func setField(field reflect.Value, defaultVal string, hasDefaultTag bool) error {
if !field.CanSet() {
return nil
}

if !shouldInitializeField(field, defaultVal) {
if !shouldInitializeField(field, defaultVal, hasDefaultTag) {
return nil
}

Expand Down Expand Up @@ -160,7 +163,7 @@ func setField(field reflect.Value, defaultVal string) error {
switch field.Kind() {
case reflect.Ptr:
if isInitial || field.Elem().Kind() == reflect.Struct {
setField(field.Elem(), defaultVal)
setField(field.Elem(), defaultVal, hasDefaultTag)
callSetter(field.Interface())
}
case reflect.Struct:
Expand All @@ -169,7 +172,7 @@ func setField(field reflect.Value, defaultVal string) error {
}
case reflect.Slice:
for j := 0; j < field.Len(); j++ {
if err := setField(field.Index(j), ""); err != nil {
if err := setField(field.Index(j), "", false); err != nil {
return err
}
}
Expand All @@ -181,14 +184,14 @@ func setField(field reflect.Value, defaultVal string) error {
case reflect.Ptr:
switch v.Elem().Kind() {
case reflect.Struct, reflect.Slice, reflect.Map:
if err := setField(v.Elem(), ""); err != nil {
if err := setField(v.Elem(), "", false); err != nil {
return err
}
}
case reflect.Struct, reflect.Slice, reflect.Map:
ref := reflect.New(v.Type())
ref.Elem().Set(v)
if err := setField(ref.Elem(), ""); err != nil {
if err := setField(ref.Elem(), "", false); err != nil {
return err
}
field.SetMapIndex(e, ref.Elem().Convert(v.Type()))
Expand Down Expand Up @@ -221,7 +224,7 @@ func isInitialValue(field reflect.Value) bool {
return reflect.DeepEqual(reflect.Zero(field.Type()).Interface(), field.Interface())
}

func shouldInitializeField(field reflect.Value, tag string) bool {
func shouldInitializeField(field reflect.Value, tag string, hasDefaultTag bool) bool {
switch field.Kind() {
case reflect.Struct:
return true
Expand All @@ -235,7 +238,7 @@ func shouldInitializeField(field reflect.Value, tag string) bool {
return field.Len() > 0 || tag != ""
}

return tag != ""
return hasDefaultTag
}

// CanUpdate returns true when the given value is an initial value of its type
Expand Down
28 changes: 27 additions & 1 deletion defaults_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -129,7 +129,8 @@ type Sample struct {

SliceWithJSON []string `default:"[\"foo\"]"`

Empty string `default:""`
Empty string `default:""`
EmptyStringPtr *string `default:""`

NoDefault *string `default:"-"`
NoDefaultStruct Struct `default:"-"`
Expand Down Expand Up @@ -312,6 +313,9 @@ func TestInit(t *testing.T) {
if sample.String != "hello" {
t.Errorf("it should initialize string")
}
if sample.EmptyStringPtr == nil || *sample.EmptyStringPtr != "" {
t.Errorf("it should initialize string pointer with empty default")
}

if sample.IntOct != 0o1 {
t.Errorf("it should initialize int with octal literal")
Expand Down Expand Up @@ -567,6 +571,28 @@ func TestInit(t *testing.T) {
}{}); err == nil {
t.Errorf("it should return error")
}

type invalidNestedDefault struct {
I []int `default:"[!]"`
}

if err := Set(&struct {
S []invalidNestedDefault
}{S: []invalidNestedDefault{{}}}); err == nil {
t.Errorf("it should return error")
}

if err := Set(&struct {
M map[string]*invalidNestedDefault
}{M: map[string]*invalidNestedDefault{"foo": {}}}); err == nil {
t.Errorf("it should return error")
}

if err := Set(&struct {
M map[string]invalidNestedDefault
}{M: map[string]invalidNestedDefault{"foo": {}}}); err == nil {
t.Errorf("it should return error")
}
})
})

Expand Down