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

Set the default value for a pointers (non-struct) when it is nil only. #24

Merged
merged 2 commits into from
Aug 27, 2021

Conversation

mmpereira2github
Copy link

Usually, in our projects, we read a JSON configuration file into a struct and invoke the defaults.Set() function to set the default values of non initialized fields. When one of the configuration parameters is a boolean and we set its default value to true, it cannot use the JSON configuration file to set it as false, because Set() assumes it using the default value and modifies it to true. In order to solve this, we decided to use pointers to boolean that can be nil when the field does not appear in the configuration file. In such a scenario, defaults.Set() works fine as expected assigning true to the boolean field, however, when in the JSON configuration file the boolean parameter is set to false, then defaults.Set() ignores that the pointer already has a value different from nil, gets the pointer value, checks that it is false, and modifies it to true what is not desired.

As a proposal, this PR just skips the setFields() function when the pointer is not nil and not a struct. Using this approach, the nil value will be the trigger to set the default value which makes sense since the Zero() value for pointers is nil.

Copy link
Owner

@creasty creasty left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you for the proposal.

Comment on lines +62 to +64
defaultValueSet := false
if isInitialValue(field) {
defaultValueSet = true
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should be more sophisticated.

Suggested change
defaultValueSet := false
if isInitialValue(field) {
defaultValueSet = true
isInitial := isInitialValue(field)
if isInitial {

String string `default:"hello"`
Duration time.Duration `default:"10s"`

IntOct int `default:"0o1"`
IntOctPtr *int `default:"0o1"`
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since its default value doesn't need to be an octal integer notation, we would like to add a more generic field like IntPtr instead.

	Int       int           `default:"1"`
+	IntPtr    *int          `default:"1"`
...
	IntOct    int    `default:"0o1"`
-	IntOctPtr *int   `default:"0o1"`

Also, I'd appreciate it if could you add test cases for pointers of other primitive types (namely *unit, *float32, and *string) and those of a slice (*[]int) and a map (*map[string]int).

@amurchick
Copy link

I also need this functionality.
When will it be in the master branch?
Thank you!

@creasty
Copy link
Owner

creasty commented Aug 27, 2021

I'm taking over

@creasty creasty merged commit b261feb into creasty:master Aug 27, 2021
creasty added a commit that referenced this pull request Aug 27, 2021
creasty added a commit that referenced this pull request Aug 27, 2021
@creasty
Copy link
Owner

creasty commented Aug 27, 2021

@amurchick
Copy link

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

Successfully merging this pull request may close these issues.

3 participants