Lazy config load behind a factory closure
byob-config.3
config
Problem: if main() always reads, parses, and validates the config file,
mytool --version and mytool --help pay a filesystem cost and can fail on
a broken config file they don't even need.
Idea: put config loading inside a lazy factory closure. Only commands that
actually dereference f.Config() trigger the load. sync.Once guarantees
one load per process.
Tradeoffs: you must remember f.Config() (invoke) instead of a bare field.
Alternative: eager load. Simpler to reason about, slower to start, and
turns "broken config file" into "can't see --help".
Design
func (f *Factory) configProvider() func() (*Config, error) {
var (
once sync.Once
cfg *Config
err error
)
return func() (*Config, error) {
once.Do(func() {
path, e := FindConfigUp("mytool.toml")
if e != nil { cfg, err = defaultConfig(), nil; return }
cfg, err = loadAndValidate(path)
})
return cfg, err
}
}
// main() never reads config; 'mytool --help' is filesystem-free.