pflag
A Go library supporting POSIX/GNU-style flags. A drop-in replacement for Go's standard flag package.
Framework
pflag
Overview
pflag is a Go library supporting POSIX/GNU-style flags. Designed as a drop-in replacement for Go's standard flag package, it enables more flexible flag handling. It's often used in combination with Cobra and is suitable for building modern CLI applications.
Details
pflag was developed to handle POSIX/GNU-style command-line flags that are not provided by the standard flag package. It supports both --flag
(long form) and -f
(short form), providing richer functionality while maintaining compatibility with the standard flag package. It's also used internally by the spf13/cobra library and is widely adopted in the Go ecosystem.
Key Features
- POSIX/GNU Compliant: Supports both
--flag
and-f
formats - Drop-in Replacement: Can directly replace the standard flag package
- Rich Flag Types: Supports various types including String, Int, Bool, Duration, Slice
- Shorthands: Can define single-character aliases
- FlagSet: Supports subcommands through independent flag sets
- Custom Flags: Enables implementation of custom flag types via pflag.Value interface
- Compatibility: Can incorporate flags defined with the standard flag package
Pros and Cons
Pros
- Standard Flag Format: Familiar interface compliant with POSIX/GNU conventions
- High Compatibility: Easy migration from existing flag code
- Flexibility: Various flag types and customization options
- Ecosystem: Excellent integration with other CLI libraries like Cobra
- Lightweight: Provides rich functionality with minimal overhead
Cons
- Standalone Use: Advanced CLI features (subcommands, help generation) are limited when used alone
- Learning Cost: Subtle differences when migrating from standard flag
- Dependencies: Creates dependency on external library
- Complex Structures: Additional frameworks needed for large-scale CLIs
Key Links
Example Usage
package main
import (
"fmt"
"os"
"github.com/spf13/pflag"
)
func main() {
// Basic flag definitions
var name = pflag.String("name", "World", "Your name")
var age = pflag.IntP("age", "a", 0, "Your age") // Shorthand 'a'
var verbose = pflag.BoolP("verbose", "v", false, "Enable verbose output")
var tags = pflag.StringSlice("tags", []string{}, "List of tags")
// Help and version flags
var help = pflag.BoolP("help", "h", false, "Show help")
var version = pflag.Bool("version", false, "Show version")
// Parse flags
pflag.Parse()
// Show help
if *help {
pflag.Usage()
return
}
// Show version
if *version {
fmt.Println("myapp version 1.0.0")
return
}
// Use flag values
fmt.Printf("Hello, %s!\n", *name)
if *age > 0 {
fmt.Printf("You are %d years old.\n", *age)
}
if *verbose {
fmt.Println("Verbose output enabled.")
fmt.Printf("Tags: %v\n", *tags)
}
// Non-flag arguments
if pflag.NArg() > 0 {
fmt.Printf("Remaining arguments: %v\n", pflag.Args())
}
}
// Example with FlagSet for subcommands
func withFlagSet() {
// Main command flags
mainFlags := pflag.NewFlagSet("main", pflag.ExitOnError)
debug := mainFlags.Bool("debug", false, "Enable debug mode")
// FlagSet for subcommands
createFlags := pflag.NewFlagSet("create", pflag.ExitOnError)
createName := createFlags.String("name", "", "Name of resource to create")
createType := createFlags.String("type", "default", "Type of resource")
deleteFlags := pflag.NewFlagSet("delete", pflag.ExitOnError)
deleteForce := deleteFlags.Bool("force", false, "Force deletion")
deleteName := deleteFlags.String("name", "", "Name of resource to delete")
// Parse main flags
mainFlags.Parse(os.Args[1:])
if *debug {
fmt.Println("Debug mode enabled")
}
// Handle subcommands
args := mainFlags.Args()
if len(args) == 0 {
fmt.Println("Please specify a subcommand: create, delete")
return
}
switch args[0] {
case "create":
createFlags.Parse(args[1:])
fmt.Printf("Creating resource: name=%s, type=%s\n", *createName, *createType)
case "delete":
deleteFlags.Parse(args[1:])
if *deleteForce {
fmt.Printf("Force deleting: %s\n", *deleteName)
} else {
fmt.Printf("Deleting: %s\n", *deleteName)
}
default:
fmt.Printf("Unknown subcommand: %s\n", args[0])
}
}