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
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,7 @@ Here are all the options available for the `env` tag:
- `,notEmpty`: make the field errors if the environment variable is empty
- `,required`: make the field errors if the environment variable is not set
- `,unset`: unset the environment variable after use
- `,emptyOverridesDefault`: treats an empty environment variable value as an explicit override of the default value

### Parse Options

Expand Down
30 changes: 17 additions & 13 deletions env.go
Original file line number Diff line number Diff line change
Expand Up @@ -537,17 +537,18 @@ func toEnvName(input string) string {

// FieldParams contains information about parsed field tags.
type FieldParams struct {
OwnKey string
Key string
DefaultValue string
HasDefaultValue bool
Required bool
LoadFile bool
Unset bool
NotEmpty bool
Expand bool
Init bool
Ignored bool
OwnKey string
Key string
DefaultValue string
HasDefaultValue bool
Required bool
LoadFile bool
Unset bool
NotEmpty bool
Expand bool
Init bool
Ignored bool
EmptyOverridesDefault bool
}

func parseFieldParams(field reflect.StructField, opts Options) (FieldParams, error) {
Expand Down Expand Up @@ -583,6 +584,8 @@ func parseFieldParams(field reflect.StructField, opts Options) (FieldParams, err
result.Expand = true
case "init":
result.Init = true
case "emptyOverridesDefault":
result.EmptyOverridesDefault = true
case "-":
result.Ignored = true
default:
Expand All @@ -600,6 +603,7 @@ func get(fieldParams FieldParams, opts Options) (val string, err error) {
fieldParams.Key,
fieldParams.DefaultValue,
fieldParams.HasDefaultValue,
fieldParams.EmptyOverridesDefault,
opts.Environment,
)

Expand Down Expand Up @@ -648,12 +652,12 @@ func getFromFile(filename string) (value string, err error) {
return string(b), err
}

func getOr(key, defaultValue string, defExists bool, envs map[string]string) (val string, exists, isDefault bool) {
func getOr(key, defaultValue string, defExists bool, emptyOverridesDefault bool, envs map[string]string) (val string, exists, isDefault bool) {
value, exists := envs[key]
switch {
case (!exists || key == "") && defExists:
return defaultValue, true, true
case exists && value == "" && defExists:
case exists && value == "" && !emptyOverridesDefault && defExists:
return defaultValue, true, true
case !exists:
return "", false, false
Expand Down
17 changes: 17 additions & 0 deletions env_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2411,3 +2411,20 @@ func TestEnvBleed(t *testing.T) {
isEqual(t, "", cfg.Foo)
})
}

func TestEmptyOverridesDefault(t *testing.T) {
type Test struct {
Foo string `env:"FOO" envDefault:"foo"`
Bar string `env:"BAR,emptyOverridesDefault" envDefault:"bar"`
NotSet string `env:"NOT_SET,emptyOverridesDefault" envDefault:"default"`
}

t.Setenv("FOO", "")
t.Setenv("BAR", "")

var cfg Test
isNoErr(t, Parse(&cfg))
isEqual(t, "foo", cfg.Foo)
isEqual(t, "", cfg.Bar)
isEqual(t, "default", cfg.NotSet)
}