This example demonstrates the RECOMMENDED way to handle defaults in confkit - using a DefaultConfig() function instead of struct tags.
Key Points
- NO "default" tags in structs - Defaults belong in code, not in struct tags
- Create a
DefaultConfig() function - Returns a struct with sensible defaults
- Use
FromDefaults() helper - Converts the struct to a configuration layer
- Defaults are queryable - Can be used for documentation generation
Benefits of This Approach
- Testable: Your defaults are in a function that can be unit tested
- Type-safe: Compiler ensures your defaults match the struct types
- Discoverable: Defaults are in one place, easy to find and review
- Flexible: Can compute defaults based on environment or other factors
- Documentation: Same defaults used at runtime and for generating docs
The Pattern
// 1. Define your config struct WITHOUT default tags
type Config struct {
Server struct {
Host string `mapstructure:"host" description:"Server bind address"`
Port int `mapstructure:"port" description:"Server listening port"`
} `mapstructure:"server"`
}
// 2. Create a function that returns defaults
func DefaultConfig() *Config {
return &Config{
Server: struct{...}{
Host: "localhost",
Port: 8080,
},
}
}
// 3. Use it with confkit
cfg := confkit.NewConfig()
cfg.Add(confkit.FromDefaults("defaults", DefaultConfig()))
Struct tags for defaults are problematic because:
- They mix concerns (structure definition vs runtime behavior)
- They're strings, losing type safety
- They can't be computed dynamically
- They're harder to test
- They duplicate information if you need defaults elsewhere
This example shows how to do it right!