go-functional-optionslisted
Install: claude install-skill muratmirgun/gophers
# Functional Options
The functional options pattern lets a constructor stay backward compatible while accepting an open-ended set of optional settings. Callers pass only what differs from the defaults; new options never break old call sites.
## Core Rules
1. **Reach for functional options at 3+ optional parameters** or whenever the API will grow.
2. **The `options` struct is unexported.** Only the package owns its shape.
3. **The `Option` interface has an unexported `apply` method.** No external package can forge an option.
4. **Defaults go inside the constructor**, before options are applied.
5. **Required parameters stay positional;** only the optional ones go through `...Option`.
6. **Prefer the interface form over closures** — it composes better with testing, debugging, and `fmt.Stringer`.
## When to Use What
| Situation | Pattern |
|---|---|
| 0–2 optional params, stable API | Plain positional or named args |
| Config that callers usually pass whole | Config struct |
| 3+ optional params, growing API | **Functional options** |
| Mix of "must set together" + "rare overrides" | Config struct + small `Option` set |
> Read [references/options-vs-struct.md](references/options-vs-struct.md) when choosing between options and a plain config struct, or designing a hybrid.
## The Canonical Pattern
```go
package db
import "go.uber.org/zap"
// options is the package's private bag of settings.
type options struct {
cache bool
logger *zap.Logger
}
// Option configu