Manage unset flag/environment variable
matteodisabatino opened this issue · 3 comments
Hi, I noticed a "strange behaviour" with flags and environment variables. This is my configuration:
type Config struct {
MyRequiredField string `env:"MY_REQUIRED_FIELD" long:"my-required-field" required:"true"`
}
func GetConfig(args []string) Config {
var c Config
if _, err := flags.ParseArgs(&c, args); err != nil {
panic(err)
}
return c
}
Now, if I launch program both this way: go run my_program.go --my-required-field=
, and this other MY_REQUIRED_FIELD= go run my_program.go
I receive no errors.
I know that both flag (first case) and environment variable (second case) are passed to the program, but they are unset. Shouldn't this be an error?
Not the author, but from a logic perspective, no- because the arguments were provided and thus satisfy the required constraint, they're just empty strings. Since the zero value of a string is, well, an empty string, this means that that constraint (at the least in theory) will always evaluate to true/pass.
Implement a second round of validation with something with more flexible options that uses a different tag name. I recommend https://pkg.go.dev/github.com/go-playground/validator/v10 and using the tag validate:"required"
(this "required" behavior matches your expectations more closely) or validate:"min=1"
.
Alternatively, just perform the additional validation yourself (if c.MyRequiredField == ""
, if len(c.MyRequiredField) == 0
, if strings.TrimSpace(c.MyRequiredField) == ""
, etc.).
For a more visual example of why this happens:
# Ensure a clean test environment.
unset TEST_ENVVAR
# Show that it is not set.
env | grep -E '^TEST_ENVVAR='
# Show that it IS set, just to an empty string.
TEST_ENVVAR= env | grep -E '^TEST_ENVVAR='
# Likewise to display it is, in fact, an actual empty string and not *unset*, as these are different.
export TEST_ENVVAR=
echo "|${TEST_ENVVAR}|"
What might be confusing you is there is a strict distinction between an environment variable not being set vs. being set to an empty string. TEST_ENVVAR=
sets it to an empty string, which is in fact a value. (Kind of like in Go, testVar := ""
IS still a value, it's just an empty string.)
@nf-brentsaner thanks for your explanation