检测未初始化的结构体字段

huangapple go评论75阅读模式
英文:

Detecting uninitialized struct fields

问题

我有一个用golang编写的服务,可以通过一些选项进行初始化。选项作为一个结构体传递给构造函数。构造函数对未包含的选项字段使用默认值。这里有一个示例:

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}
}

// 其他代码...

// 在我的代码的其他地方
o := Options{BoolOption: false}

// 将s.options.BoolOption设置为true!!!
s := New(o)

我的问题是,对于boolint选项类型,我无法确定Options结构体中的字段值是否被设置。例如,BoolOption是设置为false还是未初始化?

一种可能的解决方案是对所有Options字段使用字符串。例如,BoolOption将是"false"而不是false。然后,我可以通过检查字符串的长度来判断它是否被初始化。

是否有更好的解决方案?

英文:

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 = &quot;bar&quot;
)

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

  if len(opts.StringOption) &lt; 1 {
    opts.StringOption = DefaultStringOption
  }

  return &amp;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 &quot;false&quot; rather than false. I could then check the length of the string to check if it was initialized.

Are there better solutions?

答案1

得分: 4

用于检测未初始化的结构体字段时,某些类型具有零值,否则它们为nil(映射和通道需要使用make函数):

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

这里有一个有用的教程幻灯片。

我认为你的问题涉及创建一个默认为true的布尔值。


然而,为了你的方便,如果你将一个Option结构体传递给该函数,并且用户没有指定选项,则默认情况下它们将是false""

一种解决方案是创建一个(另一个)构造函数:func NewOptions(b bool, s string) Options

这个构造函数将使布尔值默认为true

你也可以尝试使用枚举来模拟布尔值;零值将为0。所以在Options结构体值BoolOption的类型中,你可以使用int代替bool

const (
    TRUE
    FALSE
)

你还可以将UNINITIALIZED作为零值,但我认为你只是想切换默认值,而不是检测它是否未初始化。

因此,在检查Options值时,你可以编写:

if opt.BoolOption == FALSE {
    // 使用该选项做一些事情
} else {
    // 默认选项
}

更简单的方法是将BoolOption改为notBoolOption,并将默认值设为false


或者,正如Olivia Ruth指出的,如果将字段设置为指向布尔值的指针,在“初始化”之前它将保持为nil

英文:

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 = &quot;&quot;
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

<hr>

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 &quot;&quot; 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
}

<hr>

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

<hr>

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

答案2

得分: 1

布尔类型的默认值是false。如果你注意到每次运行代码时都将选项值覆盖为true。

字符串变量的默认值是""。所以如果使用len(opts.StringOption) == 0opts.StringOption == ""来检查字符串,也可以正常工作。

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

英文:

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 == &quot;&quot; that would work as well.

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

huangapple
  • 本文由 发表于 2017年5月9日 01:47:27
  • 转载请务必保留本文链接:https://go.coder-hub.com/43854117.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定