295 lines
6.1 KiB
Markdown
295 lines
6.1 KiB
Markdown
# Builder Pattern
|
|
|
|
The builder pattern provides fine-grained control over configuration initialization and loading behavior.
|
|
|
|
## Basic Builder Usage
|
|
|
|
```go
|
|
cfg, err := config.NewBuilder().
|
|
WithDefaults(defaultStruct).
|
|
WithEnvPrefix("MYAPP_").
|
|
WithFile("config.toml").
|
|
Build()
|
|
```
|
|
|
|
## Builder Methods
|
|
|
|
### WithDefaults
|
|
|
|
Register a struct containing default values:
|
|
|
|
```go
|
|
type Config struct {
|
|
Host string `toml:"host"`
|
|
Port int `toml:"port"`
|
|
}
|
|
|
|
defaults := &Config{
|
|
Host: "localhost",
|
|
Port: 8080,
|
|
}
|
|
|
|
cfg, _ := config.NewBuilder().
|
|
WithDefaults(defaults).
|
|
Build()
|
|
```
|
|
|
|
### WithTarget
|
|
|
|
Enable type-aware mode with automatic struct population:
|
|
|
|
```go
|
|
var appConfig Config
|
|
|
|
cfg, _ := config.NewBuilder().
|
|
WithTarget(&appConfig). // Registers struct and enables AsStruct()
|
|
WithFile("config.toml").
|
|
Build()
|
|
|
|
// Access populated struct
|
|
populated, _ := cfg.AsStruct()
|
|
config := populated.(*Config)
|
|
```
|
|
|
|
### WithTagName
|
|
|
|
Use different struct tags for field mapping:
|
|
|
|
```go
|
|
type Config struct {
|
|
Server struct {
|
|
Host string `json:"host"` // Using JSON tags
|
|
Port int `json:"port"`
|
|
} `json:"server"`
|
|
}
|
|
|
|
cfg, _ := config.NewBuilder().
|
|
WithDefaults(&Config{}).
|
|
WithTagName("json"). // Use json tags instead of toml
|
|
Build()
|
|
```
|
|
|
|
Supported tag names: `toml` (default), `json`, `yaml`
|
|
|
|
### WithPrefix
|
|
|
|
Add a prefix to all registered paths:
|
|
|
|
```go
|
|
cfg, _ := config.NewBuilder().
|
|
WithDefaults(serverConfig).
|
|
WithPrefix("server"). // All paths prefixed with "server."
|
|
Build()
|
|
|
|
// Access as "server.host" instead of just "host"
|
|
host, _ := cfg.Get("server.host")
|
|
```
|
|
|
|
### WithEnvPrefix
|
|
|
|
Set environment variable prefix:
|
|
|
|
```go
|
|
cfg, err := config.NewBuilder().
|
|
WithEnvPrefix("MYAPP_").
|
|
Build()
|
|
|
|
// Reads from MYAPP_SERVER_PORT for "server.port"
|
|
```
|
|
|
|
### WithSources
|
|
|
|
Configure source precedence order:
|
|
|
|
```go
|
|
// Environment variables take highest priority
|
|
cfg, _ := config.NewBuilder().
|
|
WithSources(
|
|
config.SourceEnv,
|
|
config.SourceFile,
|
|
config.SourceCLI,
|
|
config.SourceDefault,
|
|
).
|
|
Build()
|
|
```
|
|
|
|
### WithEnvTransform
|
|
|
|
Custom environment variable name mapping:
|
|
|
|
```go
|
|
cfg, _ := config.NewBuilder().
|
|
WithEnvTransform(func(path string) string {
|
|
// Custom mapping logic
|
|
switch path {
|
|
case "server.port":
|
|
return "PORT" // Use $PORT instead of $MYAPP_SERVER_PORT
|
|
case "database.url":
|
|
return "DATABASE_URL"
|
|
default:
|
|
// Default transformation
|
|
return "MYAPP_" + strings.ToUpper(
|
|
strings.ReplaceAll(path, ".", "_"),
|
|
)
|
|
}
|
|
}).
|
|
Build()
|
|
```
|
|
|
|
### WithEnvWhitelist
|
|
|
|
Limit which configuration paths check environment variables:
|
|
|
|
```go
|
|
cfg, _ := config.NewBuilder().
|
|
WithEnvWhitelist(
|
|
"server.port",
|
|
"database.url",
|
|
"api.key",
|
|
). // Only these paths read from env
|
|
Build()
|
|
```
|
|
|
|
### WithValidator
|
|
|
|
Add validation functions that run after loading:
|
|
|
|
```go
|
|
cfg, _ := config.NewBuilder().
|
|
WithDefaults(defaults).
|
|
WithValidator(func(c *config.Config) error {
|
|
// Validate port range
|
|
port, _ := c.Get("server.port")
|
|
if p := port.(int64); p < 1024 || p > 65535 {
|
|
return fmt.Errorf("port must be between 1024-65535")
|
|
}
|
|
return nil
|
|
}).
|
|
WithValidator(func(c *config.Config) error {
|
|
// Validate required fields
|
|
return c.Validate("api.key", "database.url")
|
|
}).
|
|
Build()
|
|
```
|
|
|
|
### WithFile
|
|
|
|
Set configuration file path:
|
|
|
|
```go
|
|
cfg, _ := config.NewBuilder().
|
|
WithFile("/etc/myapp/config.toml").
|
|
Build()
|
|
```
|
|
|
|
### WithArgs
|
|
|
|
Override command-line arguments (default is os.Args[1:]):
|
|
|
|
```go
|
|
cfg, _ := config.NewBuilder().
|
|
WithArgs([]string{"--debug", "--server.port=9090"}).
|
|
Build()
|
|
```
|
|
|
|
### WithFileDiscovery
|
|
|
|
Enable automatic configuration file discovery:
|
|
|
|
```go
|
|
cfg, _ := config.NewBuilder().
|
|
WithFileDiscovery(config.FileDiscoveryOptions{
|
|
Name: "myapp",
|
|
Extensions: []string{".toml", ".conf"},
|
|
EnvVar: "MYAPP_CONFIG",
|
|
CLIFlag: "--config",
|
|
UseXDG: true,
|
|
}).
|
|
Build()
|
|
```
|
|
|
|
This searches for configuration files in:
|
|
1. Path specified by `--config` flag
|
|
2. Path in `$MYAPP_CONFIG` environment variable
|
|
3. Current directory
|
|
4. XDG config directories (`~/.config/myapp/`, `/etc/myapp/`)
|
|
|
|
## Advanced Patterns
|
|
|
|
### Type-Safe Configuration Access
|
|
|
|
```go
|
|
type AppConfig struct {
|
|
Server ServerConfig `toml:"server"`
|
|
DB DBConfig `toml:"database"`
|
|
}
|
|
|
|
var conf AppConfig
|
|
|
|
cfg, _ := config.NewBuilder().
|
|
WithTarget(&conf).
|
|
WithFile("config.toml").
|
|
Build()
|
|
|
|
// Direct struct access after building
|
|
fmt.Printf("Port: %d\n", conf.Server.Port)
|
|
|
|
// Or get updated struct anytime
|
|
latest, _ := cfg.AsStruct()
|
|
appConf := latest.(*AppConfig)
|
|
```
|
|
|
|
### Multi-Stage Validation
|
|
|
|
```go
|
|
cfg, err := config.NewBuilder().
|
|
WithDefaults(defaults).
|
|
// Stage 1: Validate structure
|
|
WithValidator(validateStructure).
|
|
// Stage 2: Validate values
|
|
WithValidator(validateRanges).
|
|
// Stage 3: Validate relationships
|
|
WithValidator(validateRelationships).
|
|
Build()
|
|
|
|
func validateStructure(c *config.Config) error {
|
|
required := []string{"server.host", "server.port", "database.url"}
|
|
return c.Validate(required...)
|
|
}
|
|
|
|
func validateRanges(c *config.Config) error {
|
|
port, _ := c.Get("server.port")
|
|
if p := port.(int64); p < 1 || p > 65535 {
|
|
return fmt.Errorf("invalid port: %d", p)
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func validateRelationships(c *config.Config) error {
|
|
// Validate that related values make sense together
|
|
// e.g., if SSL is enabled, ensure cert paths are set
|
|
return nil
|
|
}
|
|
```
|
|
|
|
### Error Handling
|
|
|
|
The builder accumulates errors and returns them on `Build()`:
|
|
|
|
```go
|
|
cfg, err := config.NewBuilder().
|
|
WithTarget(nil). // Error: nil target
|
|
WithTagName("invalid"). // Error: unsupported tag
|
|
Build()
|
|
|
|
if err != nil {
|
|
// err contains first error encountered
|
|
}
|
|
```
|
|
|
|
For panic on error use `MustBuild()`
|
|
|
|
## See Also
|
|
|
|
- [Environment Variables](env.md) - Environment configuration details
|
|
- [Live Reconfiguration](reconfiguration.md) - File watching with builder |