Appendix F. Self-referential options
This appendix presents an alternative options API for the HIT client in Chapter 6. We'll start with our current approach and then move on to the self-referential options pattern.
F.1 Struct options
Passing an Options struct directly to SendN has advantages:
- Simple: Passing an Options value to SendN is straightforward and easy to grasp.
- Explicit: All options are under a single Options type. Easy to read and maintain.
- Concise: We only declare an Options struct and some helper functions.
However, this approach has downsides as well:
- Defaults: We must pass an empty Options if we want the defaults.
- Zero-value ambiguity: Unset Options fields do not always mean using the default value. For instance, we cannot differentiate between 0 and unset integer fields.
We'll first focus on the downsides of our current approach, then we'll explore an alternative.
F.1.1 Zero value ambiguity
Consider if Options had a MaxRetries option:
type Options struct { Concurrency int MaxRetries int // Defaults to 5 if zero. }
The zero value of int, 0, makes it hard to distinguish between users wanting the default and those meaning no retries. Since 0 is ambiguous (could mean an unset field or "no retries"), we might add a boolean field like NoRetries to indicate turning off retries:
type Options struct { . . . NoRetries bool // NoRetries turns off retries. MaxRetries is ignored. }