# Packages
# README
Argument
A declarative Go library for parsing command-line arguments and environment variables into structs using struct tags. Perfect for building CLI applications with clean configuration management.
Features
- ๐ท๏ธ Declarative: Use struct tags to define argument names, environment variables, and defaults
- ๐ Multiple Sources: Supports command-line arguments, environment variables, and default values
- โก Zero Dependencies: Minimal external dependencies for core functionality
- โ Type Safe: Supports all common Go types including pointers for optional values
- ๐ Extended Duration: Enhanced
time.Duration
parsing with support for days and weeks - ๐งช Well Tested: Comprehensive test suite with BDD-style tests
Installation
go get github.com/bborbe/argument/v2
Quick Start
package main
import (
"context"
"fmt"
"log"
"github.com/bborbe/argument/v2"
)
func main() {
var config struct {
Username string `arg:"username" env:"USERNAME" default:"guest"`
Password string `arg:"password" env:"PASSWORD"`
Port int `arg:"port" env:"PORT" default:"8080"`
Debug bool `arg:"debug" env:"DEBUG"`
}
ctx := context.Background()
if err := argument.Parse(ctx, &config); err != nil {
log.Fatalf("Failed to parse arguments: %v", err)
}
fmt.Printf("Starting server on port %d for user %s\n", config.Port, config.Username)
}
Usage Examples
Basic Configuration
type Config struct {
Host string `arg:"host" env:"HOST" default:"localhost"`
Port int `arg:"port" env:"PORT" default:"8080"`
LogLevel string `arg:"log-level" env:"LOG_LEVEL" default:"info"`
}
var config Config
err := argument.Parse(context.Background(), &config)
Run with: ./app -host=0.0.0.0 -port=9090 -log-level=debug
Optional Values with Pointers
type DatabaseConfig struct {
Host string `arg:"db-host" env:"DB_HOST" default:"localhost"`
Port int `arg:"db-port" env:"DB_PORT" default:"5432"`
Timeout *int `arg:"timeout" env:"DB_TIMEOUT"` // Optional
MaxConns *int `arg:"max-conns" env:"DB_MAX_CONNS"` // Optional
}
Duration with Extended Parsing
type ServerConfig struct {
ReadTimeout time.Duration `arg:"read-timeout" env:"READ_TIMEOUT" default:"30s"`
WriteTimeout time.Duration `arg:"write-timeout" env:"WRITE_TIMEOUT" default:"1m"`
IdleTimeout time.Duration `arg:"idle-timeout" env:"IDLE_TIMEOUT" default:"2h"`
Retention time.Duration `arg:"retention" env:"RETENTION" default:"30d"` // 30 days
BackupFreq time.Duration `arg:"backup-freq" env:"BACKUP_FREQ" default:"1w"` // 1 week
}
Supported duration units: ns
, us
, ms
, s
, m
, h
, d
(days), w
(weeks)
Required Fields
type APIConfig struct {
APIKey string `arg:"api-key" env:"API_KEY"` // Required (no default)
Endpoint string `arg:"endpoint" env:"ENDPOINT"` // Required (no default)
Region string `arg:"region" env:"REGION" default:"us-east-1"`
}
// This will return an error if APIKey or Endpoint are not provided
err := argument.Parse(context.Background(), &config)
Custom Types
You can use custom types (named types with underlying primitive types) for better type safety:
type Username string
type Port int
type IsEnabled bool
type Rate float64
type AppConfig struct {
Username Username `arg:"user" env:"USERNAME" default:"guest"`
Port Port `arg:"port" env:"PORT" default:"8080"`
Debug IsEnabled `arg:"debug" env:"DEBUG" default:"false"`
Rate Rate `arg:"rate" env:"RATE" default:"1.5"`
}
var config AppConfig
err := argument.Parse(context.Background(), &config)
// Access values with type safety
fmt.Printf("Username: %s\n", string(config.Username))
fmt.Printf("Port: %d\n", int(config.Port))
fmt.Printf("Debug: %t\n", bool(config.Debug))
fmt.Printf("Rate: %f\n", float64(config.Rate))
Custom types work with all supported underlying types:
string
โtype Username string
int
,int32
,int64
,uint
,uint64
โtype Port int
bool
โtype IsEnabled bool
float64
โtype Rate float64
Supported Types
- Strings:
string
- Integers:
int
,int32
,int64
,uint
,uint64
- Floats:
float64
- Booleans:
bool
- Durations:
time.Duration
(with extended parsing) - Pointers:
*string
,*int
,*float64
, etc. (for optional values) - Custom Types: Named types with underlying primitive types
Priority Order
Values are applied in the following priority order (higher priority overwrites lower):
- Default values (from
default:
tag) - Environment variables (from
env:
tag) - Command-line arguments (from
arg:
tag)
API Reference
Parse Functions
// Parse parses arguments and environment variables (quiet mode)
func Parse(ctx context.Context, data interface{}) error
// ParseAndPrint parses and prints the final configuration values
func ParseAndPrint(ctx context.Context, data interface{}) error
Validation
// ValidateRequired checks that all required fields (no default value) are set
func ValidateRequired(ctx context.Context, data interface{}) error
Command-Line Usage
Your application will automatically support standard Go flag syntax:
# Long form with equals
./app -host=localhost -port=8080
# Long form with space
./app -host localhost -port 8080
# Boolean flags
./app -debug # sets debug=true
./app -debug=false # sets debug=false
Environment Variables
Set environment variables to configure your application:
export HOST=0.0.0.0
export PORT=9090
export DEBUG=true
./app
Error Handling
The library provides detailed error messages for common issues:
err := argument.Parse(ctx, &config)
if err != nil {
// Errors include context about what failed:
// - Missing required fields
// - Type conversion errors
// - Invalid duration formats
log.Fatal(err)
}
Testing
The library is thoroughly tested with BDD-style tests using Ginkgo and Gomega:
make test # Run all tests
make precommit # Run full development workflow
Version 2 Changes
Version 2.3.0 introduced breaking changes for better library behavior:
Parse()
no longer prints configuration by default (quieter)- New
ParseAndPrint()
function when you want to display parsed values - Focus on library-like behavior vs CLI tool behavior
Contributing
Contributions are welcome! This project follows standard Go conventions and includes:
- Comprehensive tests with Ginkgo/Gomega
- Code generation with
make generate
- Linting with
make check
- Formatting with
make format
License
This project is licensed under the BSD-style license. See the LICENSE file for details.