×

go · level 3 · unit 7 · lesson 4

  1. meet it
  2. guess first
  3. your turn
  4. fix it
  5. nailed it

Tap a green word if you get lost.

meet it

Functional options: defaults first, then each option you pass.

A constructor with many settings gets messy: NewRunner(4, 3, true, 0) says nothing about which number is which. An option is a function that changes the value being built, type Option func(*Runner), made by helpers such as WithWorkers(4). That is the pattern.

NewRunner(opts ...Option) is : the ... lets callers pass any number of options, even none, and inside the function opts is a slice. It starts from sensible defaults, then applies each option in turn.

Callers write NewRunner(WithWorkers(8), WithRetries(3)), which reads like a sentence, and adding a new option never breaks an old call.

package main
import "fmt"
type Runner struct {
	workers int
	retries int
}
type Option func(*Runner)
func WithWorkers(n int) Option {
	return func(r *Runner) { r.workers = n }
}
func WithRetries(n int) Option {
	return func(r *Runner) { r.retries = n }
}
func NewRunner(opts ...Option) *Runner {
	r := &Runner{workers: 2}
	for _, opt := range opts {
		opt(r)
	}
	return r
}
func main() {
	fmt.Printf("%+v\n", *NewRunner())
	fmt.Printf("%+v\n", *NewRunner(WithWorkers(8), WithRetries(3)))
}

%+v prints a struct with its field names, which is handy when you are checking settings.