Should I check for nil values in the constructor and then set an unexported struct field, or make the default struct value useful by checking for nil at method level?
type Foo struct{}
func (f *Foo) Baz() {}
var DefaultFoo = new(Foo)
type Bar struct {
Foo *Foo
}
func (b *Bar) Baz() {
if b.Foo == nil {
DefaultFoo.Baz()
} else {
b.Foo.Baz()
}
}
or
type Foo struct{}
func (f *Foo) Baz() {}
var DefaultFoo = new(Foo)
type Bar struct {
foo *Foo
}
func NewBar(foo *Foo) *Bar {
if foo == nil {
foo = DefaultFoo
}
return &Bar{foo}
}
func (b *Bar) Baz() {
b.foo.Baz()
}
I don't think there is a "right" answer for this.
Having said this, the approach usually seen in the Go base libraries is letting the objects be created without any constructor, with nil
or zero
values in its fields, and then make the methods have logic to use or return useful defaults.
Take a look at the http.Client
implementation for example:
https://github.com/golang/go/blob/master/src/net/http/client.go
It will basically let you create a new client by just doing:
client := &http.Client{}
You can then populate the fields of the object if you want to override defaults, otherwise it'll check for nil
in different methods to provide default behaviour, for example:
https://github.com/golang/go/blob/master/src/net/http/client.go#L195
func (c *Client) transport() RoundTripper {
if c.Transport != nil {
return c.Transport
}
return DefaultTransport
}