cxuu/go-functional-options
Use when designing a Go constructor or factory function with optional configuration — especially with 3+ optional parameters or extensible APIs. Also use when building a New* function that takes many settings, even if they don't mention "functional options" by name. Does not cover general function design (see go-functions).
npx skills add https://github.com/cxuu/golang-skills --skill go-functional-options
Functional options is a pattern where you declare an opaque Option type that records information in an internal struct. The constructor accepts a variadic number of these options and applies them to configure the result.
references/OPTIONS-VS-STRUCTS.md - Read when choosing between config structs and functional options, implementing the full interface-based option pattern, or evaluating hybrid constructor APIs.Use functional options when:
options struct - holds all configurationOption interface - with unexported apply methodWith* constructors - create optionstype Option interface {
apply(*options)
}
The unexported apply method ensures only options from this package can be used.
| Aspect | Functional Options | Config Struct |
|--------|-------------------|---------------|
| Extensibility | Add new With* functions | Add new fields (may break) |
| Defaults | Built into constructor | Zero values or separate defaults |
| Caller experience | Only specify what differs | Must construct entire struct |
| Testability | Options are comparable | Struct comparison |
| Complexity | More boilerplate | Simpler setup |
Prefer Config Struct when: Fewer than 3 options, options rarely change, all options usually specified together, or internal APIs only.
The interface approach is preferred over closure-only options because:
fmt.Stringer// 1. Unexported options struct with defaults
type options struct {
field1 Type1
field2 Type2
}
// 2. Exported Option interface, unexported method
type Option interface {
apply(*options)
}
// 3. Option type + apply + With* constructor
type field1Option Type1
func (o field1Option) apply(opts *options) { opts.field1 = Type1(o) }
func WithField1(v Type1) Option { return field1Option(v) }
// 4. Constructor applies options over defaults
func New(required string, opts ...Option) (*Thing, error) {
o := options{field1: defaultField1, field2: defaultField2}
for _, opt := range opts {
opt.apply(&o)
}
// ...
}
options struct is unexportedOption interface has unexported apply methodWith* constructor...OptionOption interface or choosing between interface and closure approachesWith* constructors, option types, or the unexported options structOption types, With* functions, or constructor behaviorTake cxuu/go-functional-options from the repository into ~/.claude/skills for personal
use, or into .claude/skills inside a project.
The agent identifies a skill by the name field in its header. Two skills with the
same name cannot sit side by side — one of them will be ignored.