4.2 KiB
4.2 KiB
Command Line Arguments
The config package supports command-line argument parsing with flexible formats and automatic type conversion.
Argument Formats
Key-Value Pairs
# Space-separated
./myapp --server.port 8080 --database.url "postgres://localhost/db"
# Equals-separated
./myapp --server.port=8080 --database.url=postgres://localhost/db
# Mixed formats
./myapp --server.port 8080 --debug=true
Boolean Flags
# Boolean flags don't require a value (assumed true)
./myapp --debug --verbose
# Explicit boolean values
./myapp --debug=true --verbose=false
Nested Paths
Use dot notation for nested configuration:
./myapp --server.host=0.0.0.0 --server.port=9090 --server.tls.enabled=true
Type Conversion
Command-line values are automatically converted to match registered types:
type Config struct {
Port int64 `toml:"port"`
Timeout time.Duration `toml:"timeout"`
Ratio float64 `toml:"ratio"`
Enabled bool `toml:"enabled"`
Tags []string `toml:"tags"`
}
// All these are parsed correctly:
// --port=8080 → int64(8080)
// --timeout=30s → time.Duration(30 * time.Second)
// --ratio=0.95 → float64(0.95)
// --enabled=true → bool(true)
// --tags=prod,stable → []string{"prod", "stable"}
Integration with flag Package
Generate flag.FlagSet
// Generate flags from registered configuration
fs := cfg.GenerateFlags()
// Parse command line
if err := fs.Parse(os.Args[1:]); err != nil {
log.Fatal(err)
}
// Apply parsed flags to configuration
if err := cfg.BindFlags(fs); err != nil {
log.Fatal(err)
}
Custom Flag Registration
fs := flag.NewFlagSet("myapp", flag.ContinueOnError)
// Add custom flags
verbose := fs.Bool("v", false, "verbose output")
configFile := fs.String("config", "config.toml", "config file path")
// Parse
fs.Parse(os.Args[1:])
// Use custom flags
if *verbose {
log.SetLevel(log.DebugLevel)
}
// Load config with custom file path
cfg, _ := config.NewBuilder().
WithFile(*configFile).
Build()
// Bind remaining flags
cfg.BindFlags(fs)
Precedence and Overrides
Command-line arguments have the highest precedence by default:
// Default precedence: CLI > Env > File > Default
cfg, _ := config.Quick(defaults, "APP_", "config.toml")
// Even if config.toml sets port=8080 and APP_PORT=9090,
// --port=7070 will win
Change precedence if needed:
cfg, _ := config.NewBuilder().
WithSources(
config.SourceEnv, // Env highest
config.SourceCLI, // Then CLI
config.SourceFile, // Then file
config.SourceDefault, // Finally defaults
).
Build()
Argument Parsing Details
Validation
- Paths must use valid identifiers (letters, numbers, underscore, dash)
- No leading/trailing dots in paths
- Empty segments not allowed (no
..in paths)
Special Cases
# Double dash stops flag parsing
./myapp --port=8080 -- --not-a-flag
# Single dash flags are ignored (not GNU-style)
./myapp -p 8080 # Ignored, use --port
# Quoted values preserve spaces
./myapp --message="Hello World" --name='John Doe'
# Escape quotes in values
./myapp --json="{\"key\": \"value\"}"
Value Parsing Rules
- Booleans:
true,false(case-sensitive) - Numbers: Standard decimal notation
- Strings: Quoted or unquoted (quotes removed if present)
- Lists: Comma-separated (when target type is slice)
Override Arguments
// Parse custom arguments instead of os.Args
customArgs := []string{"--debug", "--port=9090"}
cfg, _ := config.NewBuilder().
WithArgs(customArgs).
Build()
Error Handling
CLI parsing errors are returned from Build() or LoadCLI():
cfg, err := config.NewBuilder().
WithDefaults(&Config{}).
Build()
if err != nil {
switch {
case errors.Is(err, config.ErrCLIParse):
log.Fatal("Invalid command line arguments:", err)
default:
log.Fatal("Configuration error:", err)
}
}
See Also
- Environment Variables - Environment variable handling
- Access Patterns - Retrieving parsed values