Hunter Loftis Notes to self

Useful constructors in Go

I’m learning Go (“golang”) by building a Physically-Based Renderer and today I’ve begun refactoring pbr’s constructors based on this philosophy:

Where possible, design structs that don’t require constructors and which have useful zero values by default (point := Vector3{}). But when a constructor is necessary, follow the pattern:

func NewFoo(absolutely, required int, config ...FooConfig) *Foo

That way, a minimal call like NewFoo(1, 2) points to a useful Foo. Users with more specific requirements can specify more config:

foo := NewFoo(3, 4, FooConfig{Bar: "baz"})

Internally, the Foo struct can elegantly support FooConfig via struct embedding:

type Foo struct {
  Absolutely int
  Required int
  FooConfig
}

This enables nice default properties with easy access from the top-level Foo instance. Within the constructor:

var c FooConfig
if len(config) > 0 {
  c = config[0]
}
if c.Bar == "" {
  c.Bar = "nice default"
}

As a user:

fmt.Println(foo.Bar)  // nice default

Here’s a working example on the Go Playground.