Documentation
¶
Overview ¶
Package argument provides parsing of command-line arguments and environment variables into structs using struct tags. It supports declarative configuration management with arg, env, default, required, display, and usage tags for flexible application configuration.
See Parse() for comprehensive usage examples and supported types.
Index ¶
- func DefaultValues(ctx context.Context, data interface{}) (map[string]interface{}, error)
- func Fill(ctx context.Context, data interface{}, values map[string]interface{}) error
- func Parse(ctx context.Context, data interface{}) error
- func ParseAndPrint(ctx context.Context, data interface{}) error
- func ParseArgs(ctx context.Context, data interface{}, args []string) error
- func ParseEnv(ctx context.Context, data interface{}, environ []string) error
- func ParseOnly(ctx context.Context, data interface{}) error
- func Print(ctx context.Context, data interface{}) error
- func ValidateHasValidation(ctx context.Context, data interface{}) error
- func ValidateRequired(ctx context.Context, data interface{}) error
- type HasValidation
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func DefaultValues ¶
DefaultValues returns all default values of the given struct.
func Fill ¶
Fill populates the given struct with values from the provided map using JSON marshaling. It encodes the map to JSON and then decodes it back into the struct, allowing for flexible type conversion and nested structure population.
Types implementing encoding.TextMarshaler are converted to strings before JSON encoding to ensure compatibility with types that implement encoding.TextUnmarshaler. For slices of TextMarshaler, each element is converted to a string separately to maintain array structure in JSON, allowing proper unmarshaling into slice types.
Parameters:
- ctx: Context for error handling
- data: Pointer to struct to populate
- values: Map of field names to values
Returns error if JSON encoding or decoding fails.
func Parse ¶
Parse combines all functionality. It parses command-line arguments and environment variables into a struct using struct tags, then validates required fields are set.
Supported Types:
- Basic types: string, bool, int, int32, int64, uint, uint64, float64
- Pointer types: *float64 (optional values, nil if not provided)
- Slice types: []string, []int, []int64, []uint, []uint64, []float64, []bool
- Custom type slices: []Username where type Username string
- Custom types implementing encoding.TextUnmarshaler: For complex parsing logic
- Standard library time types:
- time.Time and *time.Time: RFC3339 format (e.g., "2006-01-02T15:04:05Z")
- time.Duration and *time.Duration: Extended format supporting days (e.g., "1d2h30m", "7d")
- github.com/bborbe/time types:
- libtime.Duration and *libtime.Duration: Extended duration with weeks (e.g., "2w", "1w3d")
- libtime.DateTime and *libtime.DateTime: Timestamp with timezone
- libtime.Date and *libtime.Date: Date only (e.g., "2006-01-02")
- libtime.UnixTime and *libtime.UnixTime: Unix timestamp (seconds since epoch)
Pointer types (*Type) are optional and will be nil if not provided or if provided as empty string. Non-pointer types will use zero values if not provided.
Slice types support comma-separated values by default (e.g., "alice,bob,charlie"). Whitespace around each element is automatically trimmed. Use the separator tag to customize the delimiter (e.g., separator:":").
Struct Tags:
- arg: Command-line argument name (required to parse field)
- env: Environment variable name (optional)
- default: Default value if not provided (optional)
- separator: Separator for slice values (default: ",", optional)
- required: Mark field as required (optional)
- display: Control how value is displayed - "length" shows only length for sensitive data (optional)
- usage: Help text for the argument (optional)
Example:
type Config struct {
Host string `arg:"host" env:"HOST" default:"localhost" usage:"Server hostname"`
Port int `arg:"port" env:"PORT" default:"8080" required:"true"`
Timeout time.Duration `arg:"timeout" default:"30s" usage:"Request timeout"`
StartAt *time.Time `arg:"start" usage:"Optional start time"`
Password string `arg:"password" env:"PASSWORD" display:"length" usage:"API password"`
Names []string `arg:"names" env:"NAMES" default:"alice,bob" usage:"User names"`
Ports []int `arg:"ports" env:"PORTS" separator:":" usage:"Port numbers"`
}
Custom types can implement encoding.TextUnmarshaler for specialized parsing:
type Broker string
func (b *Broker) UnmarshalText(text []byte) error {
value := string(text)
if !strings.Contains(value, "://") {
value = "plain://" + value // Add default schema
}
*b = Broker(value)
return nil
}
type Config struct {
Broker Broker `arg:"broker" default:"localhost:9092"`
Brokers []Broker `arg:"brokers" env:"BROKERS" usage:"Kafka brokers"`
}
Precedence: Command-line arguments override environment variables, which override defaults.
func ParseAndPrint ¶ added in v2.3.0
ParseAndPrint parses command-line arguments and environment variables into a struct, prints the parsed configuration to stdout, then validates required fields. It combines Parse() functionality with Print() output, useful for debugging and confirming configuration during application startup.
See Parse() documentation for supported types and struct tag options.
func ParseArgs ¶
ParseArgs parses command-line arguments into the given struct using arg struct tags. See Parse() documentation for supported types and struct tag options.
Parameters:
- ctx: Context for error handling
- data: Pointer to struct with arg tags
- args: Command-line arguments (typically os.Args[1:])
Returns error if parsing fails or if default values are malformed.
func ParseEnv ¶
ParseEnv parses environment variables into the given struct using env struct tags. See Parse() documentation for supported types and struct tag options.
Parameters:
- ctx: Context for error handling
- data: Pointer to struct with env tags
- environ: Environment variables (typically os.Environ())
Returns error if parsing fails.
func ParseOnly ¶ added in v2.10.0
ParseOnly parses command-line arguments and environment variables into a struct WITHOUT any validation. This is useful when you want to handle validation separately or implement custom validation logic.
ParseOnly combines arguments, environment variables, and defaults into the struct but skips both ValidateRequired and ValidateHasValidation checks.
Example custom validation workflow:
if err := argument.ParseOnly(ctx, &config); err != nil {
return err
}
// Custom validation
if config.Port < 1024 {
return errors.New(ctx, "port must be >= 1024")
}
// Then run standard validation if needed
if err := argument.ValidateRequired(ctx, &config); err != nil {
return err
}
if err := argument.ValidateHasValidation(ctx, &config); err != nil {
return err
}
See Parse() documentation for supported types and struct tag options.
func Print ¶
Print all configured arguments. Set display:"hidden" to hide or display:"length" to only print the arguments length.
func ValidateHasValidation ¶ added in v2.10.0
ValidateHasValidation validates data using the HasValidation interface. It first checks if the top-level struct implements HasValidation. Then it iterates through struct fields:
- For slices: validates the slice type first, then falls back to validating each element
- For other types: validates if they implement HasValidation
Important: ValidateHasValidation runs on ALL fields that implement HasValidation, regardless of whether they have the `required:"true"` tag. This is by design:
- The `required` tag checks if a field is present (non-zero)
- The Validate() method checks if a field's value is valid
These are separate concerns. If you have an optional field with a default value, that default value should still be validated. If you want zero values to be valid for optional fields, your Validate() implementation should explicitly handle that:
func (p Port) Validate(ctx context.Context) error {
if p == 0 {
return nil // zero value is valid for optional ports
}
if p < 1024 {
return fmt.Errorf("port must be >= 1024")
}
return nil
}
Returns the first validation error encountered.
Example usage (automatic validation via Parse):
type Port int
func (p Port) Validate(ctx context.Context) error {
if p < 1 || p > 65535 {
return fmt.Errorf("port must be between 1 and 65535, got %d", p)
}
return nil
}
type Config struct {
Port Port `arg:"port" default:"8080"`
}
var config Config
if err := argument.Parse(ctx, &config); err != nil {
// Parse automatically calls ValidateHasValidation
// Validation error will be returned if port is out of range
}
Example usage (manual validation workflow):
var config Config
if err := argument.ParseOnly(ctx, &config); err != nil {
return err
}
// Custom logic here (e.g., override certain fields, apply business rules)
if config.Port == 0 {
config.Port = 8080
}
// Then run standard validation
if err := argument.ValidateRequired(ctx, &config); err != nil {
return err
}
if err := argument.ValidateHasValidation(ctx, &config); err != nil {
return err
}
For slice validation, the slice type is checked first:
type Brokers []Broker
func (b Brokers) Validate(ctx context.Context) error {
if len(b) == 0 {
return fmt.Errorf("at least one broker required")
}
// Will automatically validate each Broker if it implements HasValidation
return nil
}
func ValidateRequired ¶
ValidateRequired fields are set and returns an error if not.
Types ¶
type HasValidation ¶ added in v2.10.0
type HasValidation interface {
// Validate performs validation logic and returns an error if validation fails.
// The context can be used for cancellation and timeout handling.
Validate(ctx context.Context) error
}
HasValidation defines the interface that validators must implement. It provides a single method for validating data with context support. Types implementing this interface can define custom validation logic beyond the built-in required field validation.
Example:
type Port int
func (p Port) Validate(ctx context.Context) error {
if p < 1024 {
return errors.New(ctx, "port must be >= 1024")
}
return nil
}
For more complex validation scenarios (e.g., field comparisons, conditional validation, validation helpers), see github.com/bborbe/validation which provides additional validation utilities and patterns that work well with this interface.