Answers:
一种可能的想法是编写单独的构造函数
//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
}
NewSomething
,甚至田野Text
和DefaultText
,但就是不出口的结构类型something
。
reflect.New()
例如,通过),则不能期望它知道您的特殊命名的工厂功能。我认为,在那种情况下,只要不更改语言本身,就只能使用一个接口(库可以检查)。
强制方法获取结构(构造方法)。
一个好的设计是使您的类型不导出,但提供一个类似NewMyType()的导出构造函数,您可以在其中正确初始化您的struct / type。还返回一个接口类型,而不是具体类型,并且该接口应包含其他人希望对您的值进行的操作。当然,您的具体类型必须实现该接口。
这可以通过简单地使类型本身不导出来完成。您可以导出函数NewSomething,甚至可以导出字段Text和DefaultText,但不要导出结构类型
为自己的模块自定义它的另一种方法是使用Config结构设置默认值(链接中的选项5),但这不是一个好方法。
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
}
这使我们可以使用导出的Candidate接口声明函数参数类型。从该解决方案中可以看到的唯一缺点是,我们所有的方法都需要在接口定义中声明,但是您可能会认为这是一种好习惯。
Votes unit32
应该是Votes uint32
有一种使用标记执行此操作的方法,它允许多个默认值。
假设您具有以下结构,带有2个默认标记default0和default1。
type A struct {
I int `default0:"3" default1:"42"`
S string `default0:"Some String..." default1:"Some Other String..."`
}
现在可以设置默认值。
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...
}
如果您对更复杂的示例感兴趣,例如使用切片和地图,那么请看一下creasty / defaultse
来自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
}
type Config struct {
AWSRegion string `default:"us-west-2"`
}