如何在Go结构中设置默认值

Pra*_*eek 112 struct initialization default-value go

以下问题有多种答案/技巧:

  1. 如何设置golang结构的默认值?
  2. 如何在golang中初始化结构

我有几个答案,但需要进一步讨论.

vod*_*095 82

一个可能的想法是编写单独的构造函数

//Something is the structure we work with
type Something struct {
     Text string 
     DefaultText string 
} 
// NewSomething create new instance of Something
func NewSomething(text string) Something {
   something := Something{}
   something.Text = text
   something.DefaultText = "default text"
   return something
}
Run Code Online (Sandbox Code Playgroud)

  • @Prateek是的,你可以强迫人们使用这个构造函数,如果你只是让类型本身未导出.您可以导出函数`NewSomething`甚至是`Text`和`DefaultText`字段,但只是不导出struct类型`something`. (25认同)
  • 是的,这是我在答案中也提到的方法之一,但我们无法强迫任何人只使用此功能. (5认同)
  • 问题更糟......如果使用第三方(例如库)来实例化您的结构(例如通过“reflect.New()”),则不能指望它知道您的特殊命名工厂功能。在这种情况下,我认为,如果语言本身没有改变,*只有*一个接口(库可以检查)就可以了。 (3认同)
  • 设置默认值很好,但有时,我可能想覆盖默认值。在这种情况下,我将无法使用非默认值初始化结构。对我来说有点烦人 (2认同)

Pra*_*eek 55

  1. 强制方法获取结构(构造方式).

    一个好的设计是使你的类型不被导出,但提供一个导出的构造函数,如NewMyType(),你可以在其中正确初始化你的结构/类型.还返回接口类型而不是具体类型,接口应包含其他人想要对您的值执行的所有操作.您的具体类型当然必须实现该接口.

    这可以通过简单地使类型本身未导出来完成.您可以导出函数NewSomething甚至字段Text和DefaultText,但只是不导出struct类型的东西

  2. 为您自己的模块定制它的另一种方法是使用Config结构来设置默认值(链接中的选项5)虽然不是一个好方法.

  • 现在这是一个断开的链接(404):http://joneisen.tumblr.com/post/53695478114/golang-and-default-values (4认同)
  • 它可以在[wayback machine]中找到(https://web.archive.org/web/20160818125551/https://joneisen.tumblr.com/post/53695478114/golang-and-default-values). (3认同)

wol*_*109 24

Victor Zamanian回答选项1的一个问题是,如果未导出类型,则包的用户不能将其声明为函数参数的类型等.解决此问题的方法之一是导出接口而不是结构例如

package candidate
// Exporting interface instead of struct
type Candidate interface {}
// Struct is not exported
type candidate struct {
    Name string
    Votes uint32 // Defaults to 0
}
// We are forced to call the constructor to get an instance of candidate
func New(name string) Candidate {
    return candidate{name, 0}  // enforce the default value here
}
Run Code Online (Sandbox Code Playgroud)

这让我们可以使用导出的Candidate接口声明函数参数类型.我可以从这个解决方案中看到的唯一缺点是我们所有的方法都需要在接口定义中声明,但你可以说这无论如何都是好的做法.


RdB*_*RdB 6

来自https://golang.org/doc/ effective_go.html# composite_literals :

有时零值不够好,需要初始化构造函数,如本例中派生自包 os.

    func NewFile(fd int, name string) *File {
      if fd < 0 {
        return nil
      }
      f := new(File)
      f.fd = fd
      f.name = name
      f.dirinfo = nil
      f.nepipe = 0
      return f
}
Run Code Online (Sandbox Code Playgroud)


Mik*_*ico 6

有一种使用标记执行此操作的方法,它允许多个默认值。

假设您具有以下结构,带有2个默认标记default0default1

type A struct {
   I int    `default0:"3" default1:"42"`
   S string `default0:"Some String..." default1:"Some Other String..."`
}
Run Code Online (Sandbox Code Playgroud)

现在可以设置默认值。

func main() {

ptr := &A{}

Set(ptr, "default0")
fmt.Printf("ptr.I=%d ptr.S=%s\n", ptr.I, ptr.S)
// ptr.I=3 ptr.S=Some String...

Set(ptr, "default1")
fmt.Printf("ptr.I=%d ptr.S=%s\n", ptr.I, ptr.S)
// ptr.I=42 ptr.S=Some Other String...
}
Run Code Online (Sandbox Code Playgroud)

是操场上的完整节目

如果您对更复杂的示例感兴趣,例如使用切片和地图,那么请看一下creasty / defaultse

  • 这是一个不错的选择,但它不是来自“golang”。您有一个使用反射的通用构造函数。真正的默认值将在每个新的结构实例上自动设置。 (2认同)