diff --git a/README.md b/README.md index 5c7da5c6..db707306 100644 --- a/README.md +++ b/README.md @@ -261,7 +261,7 @@ holster.IsZero(value) // Returns true if 'value' is zero (the default golang value) holster.IsZeroValue(reflect.ValueOf(value)) -// If 'value' is empty or of zero value, assign the default value. +// If 'dest' is empty or of zero value, assign the default value. // This panics if the value is not a pointer or if value and // default value are not of the same type. var config struct { @@ -273,7 +273,16 @@ holster.SetDefault(&config.Bar, 200) // Supply additional default values and SetDefault will // choose the first default that is not of zero value -// holster.SetDefault(&config.Foo, os.Getenv("FOO"), "default") +holster.SetDefault(&config.Foo, os.Getenv("FOO"), "default") + +// Use 'SetOverride() to assign the first value that is not empty or of zero +// value. The following will override the config file if 'foo' is provided via +// the cli or defined in the environment. + +loadFromFile(&config) +argFoo = flag.String("foo", "", "foo via cli arg") + +holster.SetOverride(&config.Foo, *argFoo, os.Env("FOO")) ``` ## GetEnv diff --git a/set_default.go b/set_default.go index 032d8f70..b3817913 100644 --- a/set_default.go +++ b/set_default.go @@ -19,10 +19,10 @@ import ( "reflect" ) -// If 'value' is empty or of zero value, assign the default value. +// If 'dest' is empty or of zero value, assign the default value. // This panics if the value is not a pointer or if value and // default value are not of the same type. -// var config struct { +// var config struct { // Verbose *bool // Foo string // Bar int @@ -51,6 +51,41 @@ func SetDefault(dest interface{}, defaultValue ...interface{}) { } } +// Assign the first value that is not empty or of zero value. +// This panics if the value is not a pointer or if value and +// default value are not of the same type. +// var config struct { +// Verbose *bool +// Foo string +// Bar int +// } +// +// loadFromFile(&config) +// argFoo = flag.String("foo", "", "foo via cli arg") +// +// // Override the config file if 'foo' is provided via +// // the cli or defined in the environment. +// holster.SetOverride(&config.Foo, *argFoo, os.Env("FOO")) +// +// Supply additional values and SetOverride() will +// choose the first value that is not of zero value. If all +// values are empty or zero the 'dest' will remain unchanged. +func SetOverride(dest interface{}, values ...interface{}) { + d := reflect.ValueOf(dest) + if d.Kind() != reflect.Ptr { + panic("holster.SetOverride: Expected first argument to be of type reflect.Ptr") + } + d = reflect.Indirect(d) + // Use the first non zero value value we find + for _, value := range values { + v := reflect.ValueOf(value) + if !IsZeroValue(v) { + d.Set(reflect.ValueOf(value)) + return + } + } +} + // Returns true if 'value' is zero (the default golang value) // var thingy string // holster.IsZero(thingy) == true