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

Problem with bool variable in YAML file #61

Open
dikkini opened this issue Nov 10, 2020 · 14 comments
Open

Problem with bool variable in YAML file #61

dikkini opened this issue Nov 10, 2020 · 14 comments
Labels
discussion Running discussion proposal

Comments

@dikkini
Copy link

dikkini commented Nov 10, 2020

yaml file

isdebug: false
rule:
  cachesize: 10485760000

golang struct

type AppConfig struct {
	IsDebug bool `env:"RE_IS_DEBUG" env-required:"true"`
	Rule struct {
		CacheSize          int    `env:RULE_CACHE_SIZE" env-required:"true"`
        }

i got an error field \"IsDebug\" is required but the value is not provided", but if set isdebug: true - all ok, config parse without any errors.

@dikkini
Copy link
Author

dikkini commented Nov 11, 2020

i made some research and found place where shit happened.
func isZero(v reflect.Value) bool, line 559, return !v.Bool(), v.Bool() equal false and !fasle == true and this function returns true.

@ilyakaznacheev ilyakaznacheev added bug Something isn't working discussion Running discussion labels Nov 29, 2020
@ilyakaznacheev
Copy link
Owner

Hi @dikkini, this is kinda expected behavior: false is a zero value for bool, so it's difficult to decide from the Go perspective, was the value not provided at all, or does it have a zero value.

A possible solution is to use a pointer instead:

type AppConfig struct {
	IsDebug *bool `env:"RE_IS_DEBUG" env-required:"true"`
}

yep, it doesn't look so convenient, but this way you may Go be able to clearly differentiate between the zero value (default value) of the variable and the absence of the variable.

The same goes for json, toml, etc. In theory, it is possible to check if the field is missing instead of filling it with zero value, but in Go it is made by means of pointers. So if you want to apply the same checks for the value instead of the pointer, it would require writing a custom unmarshaller for each supported file format, which is definitely out of the library scope for now.

@dikkini
Copy link
Author

dikkini commented Nov 29, 2020

You can create map for required values and check is key exists in map. What do you think?

@ilyakaznacheev ilyakaznacheev added proposal and removed bug Something isn't working labels Nov 29, 2020
@dikkini
Copy link
Author

dikkini commented Dec 1, 2020

And i pretty sure that other libraries dont have problems with negative bool variables, but this library does not allow it's users to use negative bool variable - it means - it does not support bool variables at all.

@ilyakaznacheev
Copy link
Owner

I do not agree with your point about bool variable support - if you don't use pointers, zero value always treated like "not provided" - same with json, yaml, etc.

But I will think about this proposal, maybe we will give it a try, or will find a better solution.

@dikkini
Copy link
Author

dikkini commented Dec 1, 2020

I do not agree with your point about bool variable support - if you don't use pointers, zero value always treated like "not provided" - same with json, yaml, etc.

I agree, but use bool variable without PTR useless, so is it worth to write about it in README?

But I will think about this proposal, maybe we will give it a try, or will find a better solution.

I still has an error.

type AppConfig struct {
	IsDebug *bool `env:"RE_IS_DEBUG" env-required:"true"`
}

config = &AppConfig{}
err := cleanenv.ReadConfig("config.yml", &config)

error: wrong type ptr

@ilyakaznacheev
Copy link
Owner

@dikkini its because you have a double pointer to AppConfig here

@AlexanderKudzevich
Copy link

AlexanderKudzevich commented Feb 22, 2021

Hello. There is any way to use it with "env-default" and "yaml"? Is there any other solution for using bool type?

@ilyakaznacheev
Copy link
Owner

No, the pointer is the only way I know to differentiate between true, false and "not provided" in this case.

@mhSangar
Copy link

mhSangar commented Mar 17, 2021

Regarding this issue, I'm trying to print the description of bool variables that have an env-default:false, but their description and default values are not being shown.

config definition

ToFile bool          `env:"LOG_TO_FILE"  env-default:false          env-description:"Whether to print to terminal or write to a file."`
File string          `env:"LOG_FILE"     env-default:"indexer.log"  env-description:"If LOG_TO_FILE is set, this will be the file used for the logs."`

print on terminal

  LOG_TO_FILE bool
    	
  LOG_FILE string
    	If LOG_TO_FILE is set, this will be the file used for the logs.

Is it related? Is there a fix for this? I don't think I can use pointers in my case, as I'm reading from a literal value.

EDIT:
It seems like the default value must be set as a string, or it would not be read from env-default.

@ilyakaznacheev
Copy link
Owner

@mhSangar it has to be quoted, this is how tags in Golang work

@ilyakaznacheev
Copy link
Owner

Closed because no better way to differentiate missing bool field and false bool field found. Use bool pointer.

@haithngn
Copy link

It should be mentioned in the ReadMe file :(.
I have spent 2h to find the rootcause and this ticket.

@ilyakaznacheev
Copy link
Owner

@haithngn makes sense. I'll add a note.

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

No branches or pull requests

5 participants