argument

package module
v2.5.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Oct 15, 2025 License: BSD-2-Clause Imports: 12 Imported by: 1

README

Argument

Go Version Go Reference License

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:

  • stringtype Username string
  • int, int32, int64, uint, uint64type Port int
  • booltype IsEnabled bool
  • float64type 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):

  1. Default values (from default: tag)
  2. Environment variables (from env: tag)
  3. 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.

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func DefaultValues

func DefaultValues(ctx context.Context, data interface{}) (map[string]interface{}, error)

DefaultValues returns all default values of the given struct.

func Fill

func Fill(ctx context.Context, data interface{}, values map[string]interface{}) error

Fill the given map into the struct.

func Parse

func Parse(ctx context.Context, data interface{}) error

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)
  • 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.

Struct Tags:

  • arg: Command-line argument name (required to parse field)
  • env: Environment variable name (optional)
  • default: Default value if not provided (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"`
}

Precedence: Command-line arguments override environment variables, which override defaults.

func ParseAndPrint added in v2.3.0

func ParseAndPrint(ctx context.Context, data interface{}) error

func ParseArgs

func ParseArgs(ctx context.Context, data interface{}, args []string) error

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

func ParseEnv(ctx context.Context, data interface{}, environ []string) error

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 Print

func Print(ctx context.Context, data interface{}) error

Print all configured arguments. Set display:"hidden" to hide or display:"length" to only print the arguments length.

func ValidateRequired

func ValidateRequired(ctx context.Context, data interface{}) error

ValidateRequired fields are set and returns an error if not.

Types

This section is empty.

Directories

Path Synopsis

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL