go · level 3 · unit 7 · lesson 4
- meet it
- guess first
- your turn
- fix it
- 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.
guess first
The same option twice. What does the runner end up with?
Guess before you run it. Wrong guesses are how you learn, and nothing is marked.
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() {
r := NewRunner(WithWorkers(5), WithRetries(2), WithWorkers(1))
fmt.Println(r.workers, r.retries)
}
your turn
Your turn. Finish an option and use it.
Fill in the field that WithRetries should set, then choose how many retries the runner gets.
output
press run to see what happens
fix it
The runner ignores the worker count. Can you fix it?
output
press run to see what happens
- You asked for 8 workers and got 2. What happens after the options have run?
- The default is set after the loop, so it overwrites whatever the options chose.
- Set the default first,
r := &Runner{workers: 2}, and delete the liner.workers = 2.
nailed it
your constructors read like a sentence. :D
- An option is a function that changes one setting.
- A variadic
...Optionparameter takes any number of them. - Start from defaults, then apply each option in order.
new words in your collection
- functional option
- variadic
This lesson isn’t saved. A free account remembers every lesson you finish.