GitHub - agilira/flash-flags: FlashFlags is an ultra-fast, zero-dependency, lock-free command-line flag parsing library for Go. Originally built for Argus, it provides great performance while maintaining simplicity and ease of use. (original) (raw)

FlashFlags: Ultra-fast command-line flag parsing for Go

an AGILira library

CI/CD Pipeline CodeQL Security Go Report Card Coverage GoDoc Mentioned in Awesome Go

FlashFlags is an ultra-fast, zero-dependency, lock-free command-line flag parsing library for Go. Originally built for Argus, it provides great performance while maintaining simplicity and ease of use. FlashFlags serves as the core parsing engine for our CLI framework Orpheus.

Live Demo

FeaturesQuick StartPerformanceDemoFlag TypesConfigurationExamples

Features

Security Features

Flash-flags provides comprehensive security hardening:

Security overhead: Only 132ns per operation (17%) for complete protection

Compatibility and Support

FlashFlags is designed for Go 1.23+ environments and follows Long-Term Support guidelines to ensure consistent performance across production deployments.

Performance

FlashFlags delivers exceptional performance with security-hardened parsing:

AMD Ryzen 5 7520U 
BenchmarkFlashFlags-8      1,294,699    924 ns/op     945 B/op    11 allocs/op
BenchmarkStdFlag-8         1,527,176    792 ns/op     945 B/op    13 allocs/op  
BenchmarkPflag-8             785,904   1322 ns/op    1569 B/op    21 allocs/op  
BenchmarkGoFlags-8           147,394   7460 ns/op    5620 B/op    61 allocs/op  
BenchmarkKingpin-8           150,154   7567 ns/op    6504 B/op    97 allocs/op  

Only 132ns overhead for complete protection against injection attacks

Reproduce benchmarks:

cd benchmarks && go test -bench=. -benchmem

Quick Start

Installation

go get github.com/agilira/flash-flags

Basic Usage

package main

import ( "fmt" "os"

"github.com/agilira/flash-flags"

)

func main() { // Create flag set fs := flashflags.New("myapp")

// Register flags
host := fs.StringVar("host", "h", "localhost", "Server host")
port := fs.IntVar("port", "p", 8080, "Server port")
verbose := fs.BoolVar("verbose", "v", false, "Enable verbose logging")

// Parse arguments
if err := fs.Parse(os.Args[1:]); err != nil {
    if err.Error() == "help requested" {
        os.Exit(0) // Help was shown
    }
    fmt.Printf("Error: %v\n", err)
    os.Exit(1)
}

// Use flags
fmt.Printf("Server starting on %s:%d (verbose: %t)\n", *host, *port, *verbose)

}

Usage Examples

Basic usage

./myapp --host 0.0.0.0 --port 3000 --verbose

Short flags with space

./myapp -h 0.0.0.0 -p 3000 -v

Short flags with equals (NEW!)

./myapp -h=192.168.1.1 -p=8080 -v=true

Combined short flags (NEW!)

./myapp -hvp 3000 # -h -v -p 3000 ./myapp -abc # -a -b -c (all boolean)

Mixed formats

./myapp --host=192.168.1.1 -vp 8080 --debug=false

Environment variables + CLI

MYAPP_HOST=api.example.com ./myapp -p=3000 --verbose

Help

./myapp --help

Flag Syntax

FlashFlags supports comprehensive POSIX/GNU-style flag syntax for maximum compatibility:

Long Flags

--flag value # Space-separated value --flag=value # Equals-separated value
--boolean-flag # Boolean without value (true) --boolean-flag=false # Explicit boolean value

Short Flags

-f value # Space-separated value -f=value # Equals-separated value (NEW!) -b # Boolean short flag (true) -b=false # Explicit boolean value

Combined Short Flags

-abc # Equivalent to -a -b -c (all boolean) -abc value # Last flag gets the value: -a -b -c value -vdp 8080 # Verbose + debug + port: -v -d -p 8080

Rules for combined flags:

Drop-in Stdlib Replacement

Flash-flags includes a complete drop-in replacement for Go's standard flag package. Migrate with zero code changes:

// Before - using stdlib import "flag"

// After - using flash-flags import "github.com/antonio-giordano/flash-flags/stdlib/flag"

// All your existing code works unchanged! var name = flag.String("name", "default", "description") var count = flag.Int("count", 42, "number of items")

func main() { flag.Parse() fmt.Printf("Name: %s, Count: %d\n", *name, *count)

// Full remaining arguments support
for i := 0; i < flag.NArg(); i++ {
    fmt.Printf("Arg[%d]: %s\n", i, flag.Arg(i))
}

}

See the stdlib example for a complete working demonstration.

Examples

Supported Flag Types

Type Go Type Example Description
string string --name "John" Text values
int int --port 8080 Integer numbers
bool bool --verbose Boolean flags
float64 float64 --rate 0.75 Floating point numbers
duration time.Duration --timeout 30s Time durations
stringSlice []string --tags web,api Comma-separated lists

Configuration Priority

FlashFlags applies configuration in this priority order (higher numbers override lower):

  1. Default values (lowest priority)
  2. Configuration file values
  3. Environment variables
  4. Command-line arguments (highest priority)

Configuration File Example

{ "host": "0.0.0.0", "port": 3000, "workers": 8, "enable-tls": true, "tags": ["web", "api", "production"], "timeout": "60s" }

Environment Variables

With prefix

export MYAPP_HOST=localhost export MYAPP_PORT=8080

Custom names

export DATABASE_URL=postgres://...

Validation & Constraints

// Custom validation fs.SetValidator("port", func(val interface{}) error { port := val.(int) if port < 1024 || port > 65535 { return fmt.Errorf("port must be between 1024 and 65535") } return nil })

// Required flags fs.SetRequired("api-key")

// Flag dependencies fs.SetDependencies("tls-cert", "enable-tls")

Real-World Example

package main

import ( "fmt" "log" "os" "time"

"github.com/agilira/flash-flags"

)

func main() { fs := flashflags.New("webserver") fs.SetDescription("High-performance web server") fs.SetVersion("v1.0.0")

// Server configuration
host := fs.StringVar("host", "h", "localhost", "Server host")
port := fs.IntVar("port", "p", 8080, "Server port")
workers := fs.Int("workers", 4, "Number of worker threads")

// TLS configuration  
enableTLS := fs.Bool("enable-tls", false, "Enable TLS")
tlsCert := fs.String("tls-cert", "", "TLS certificate file")
tlsKey := fs.String("tls-key", "", "TLS private key file")

// Performance tuning
timeout := fs.Duration("timeout", 30*time.Second, "Request timeout")
maxConns := fs.Int("max-connections", 1000, "Maximum connections")

// Logging
logLevel := fs.String("log-level", "info", "Log level (debug, info, warn, error)")
logFile := fs.String("log-file", "", "Log file path (empty for stdout)")

// Environment and config
fs.SetEnvPrefix("WEBSERVER")
fs.AddConfigPath("./config")
fs.AddConfigPath("/etc/webserver")

// Organize help output
fs.SetGroup("host", "Server Options")
fs.SetGroup("port", "Server Options")
fs.SetGroup("workers", "Server Options")
fs.SetGroup("enable-tls", "TLS Options")
fs.SetGroup("tls-cert", "TLS Options")
fs.SetGroup("tls-key", "TLS Options")

// Validation
fs.SetValidator("port", func(val interface{}) error {
    port := val.(int)
    if port < 1 || port > 65535 {
        return fmt.Errorf("port must be between 1 and 65535")
    }
    return nil
})

fs.SetValidator("log-level", func(val interface{}) error {
    level := val.(string)
    validLevels := []string{"debug", "info", "warn", "error"}
    for _, valid := range validLevels {
        if level == valid {
            return nil
        }
    }
    return fmt.Errorf("log-level must be one of: debug, info, warn, error")
})

// Dependencies
fs.SetDependencies("tls-cert", "enable-tls")
fs.SetDependencies("tls-key", "enable-tls")

// Parse
if err := fs.Parse(os.Args[1:]); err != nil {
    if err.Error() == "help requested" {
        os.Exit(0)
    }
    log.Fatalf("Error: %v", err)
}

// Use configuration
fmt.Printf("Starting web server:\n")
fmt.Printf("  Host: %s\n", *host)
fmt.Printf("  Port: %d\n", *port)
fmt.Printf("  Workers: %d\n", *workers)
fmt.Printf("  TLS: %v\n", *enableTLS)
fmt.Printf("  Timeout: %v\n", *timeout)
fmt.Printf("  Max Connections: %d\n", *maxConns)
fmt.Printf("  Log Level: %s\n", *logLevel)
if *logFile != "" {
    fmt.Printf("  Log File: %s\n", *logFile)
}

// Start your server here...

}

License

flash-flags is licensed under the Mozilla Public License 2.0.


flash-flags • an AGILira library