Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Manage unset flag/environment variable #402

Open
matteodisabatino opened this issue Feb 15, 2024 · 3 comments
Open

Manage unset flag/environment variable #402

matteodisabatino opened this issue Feb 15, 2024 · 3 comments

Comments

@matteodisabatino
Copy link

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?

@nf-brentsaner
Copy link

nf-brentsaner commented Jul 12, 2024

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.).

@nf-brentsaner
Copy link

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.)

@matteodisabatino
Copy link
Author

@nf-brentsaner thanks for your explanation

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants