5

I have a service, written in golang, that can be initialized with some options. Options are passed as a struct to a constructor function. The constructor function uses default values for option fields that weren't included. Here's an example:

type Service struct {
  options Options
}

type Options struct {
  BoolOption bool
  StringOption string
}

const (
  DefaultBoolOption = true
  DefaultStringOption = "bar"
)

func New(opts Options) *Service {
  if !opts.BoolOption {
    opts.BoolOption = DefaultBoolOption
  }

  if len(opts.StringOption) < 1 {
    opts.StringOption = DefaultStringOption
  }

  return &Service{options: opts,}
}

...

// elsewhere in my code
o := Options{BoolOption: false,}

// sets s.options.BoolOption to true!!!
s := New(o)

My problem is that for bool or int option types, I can't tell whether or not a field value was set in the Options struct. For example, was BoolOption set to false or just not initialized?

One possible solution would be to use strings for all of my Options fields. For instance, BoolOption would be "false" rather than false. I could then check the length of the string to check if it was initialized.

Are there better solutions?

5
  • 1
    Related / possible duplicate of How do I represent an Optional String in Go? Commented May 8, 2017 at 18:04
  • 1
    If you want it to be explicitly optional (and you care about uninitialized vs default value), you probably want to use *bool instead of bool. It makes things a bit harder to deal with though, so make sure you need to. Commented May 8, 2017 at 18:55
  • @OliviaRuth: yeah, I think that's my only real solution. But like you said, it makes things slightly more complicated. Maybe it's not that important for me to have optional inputs. Commented May 8, 2017 at 20:01
  • 3
    Worth noting that if the default for the boolean is "true", you should probably invert the boolean. For example, if the boolean is "logInput", and you want it to default to on, you should probably make the boolean option instead be "noLog" and default to false. This follows the Go axiom of making default values useful. Commented May 8, 2017 at 20:34
  • You have two options in here, one is use pointer for fields, the second is encapsulate the Options struct and generate Get and Set methods for the fields that record/check if is set. Commented May 9, 2017 at 1:40

2 Answers 2

4

For detecting uninitialized struct fields, as a rule certain types have zero values, they are otherwise nil (maps and channels need to be maked):

var i int     // i = 0
var f float64 // f = 0
var b bool    // b = false
var s string  // s = ""
var m chan int// c = nil

There is a tour slide which is useful.

I think you're problem involves creating a default boolean value of true


For your sake, however, if you are passing an Option struct into that function, and the user did not specify the options, then yes they will be false and "" by default.

One solution is to create a(nother) constructor: func NewOptions(b bool, s string) Options

This constructor would make the bool default true.

You could also try an enum to simulate a boolean; the zero value will be 0. So instead of type bool for the Options struct value BoolOption, you could use int:

const (
        TRUE
        FALSE
)

You could also have a UNINITIALIZED as zero, but I think you just want to switch the default value, rather than detecting that it is uninitialized.

So when checking a value of Options, you could write:

if opt.BoolOption == FALSE {
    // Do something with the option
} else {
    // The default option
}

A bit simpler would be to make the BoolOption into notBoolOption, and have the default be false.


Or, as Olivia Ruth points out, if you have the field as a pointer to a boolean, it will be remain nil until "initialized".

Sign up to request clarification or add additional context in comments.

1 Comment

Thanks for this. I think the only other option, as @Olivia Ruth points out, I could use a pointer inside by options struct and check for nil.
1

The default value for a bool is false. If you notice that you are overwriting the options value to true every time you run the code.

The default values of a strings variable is "". So if check the string with len(opts.StringOption) == 0 or opts.StringOption == "" that would work as well.

https://play.golang.org/p/jifZZvoBVZ

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.