or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

docs

advanced-features.mdflag-access.mdflag-definition.mdflag-types.mdflagset-methods.mdgo-integration.mdindex.mdusage-help.md
tile.json

flag-access.mddocs/

Flag Value Access

This document covers accessing flag values after parsing, including lookups, argument access, and checking flag state.

Import

import "github.com/spf13/pflag"

Flag Lookup

Lookup

func Lookup(name string) *Flag

Return the Flag structure of the named command-line flag, or nil if none exists. Operates on the global CommandLine FlagSet.

Usage:

pflag.String("output", "out.txt", "output file")
pflag.Parse()

flag := pflag.Lookup("output")
if flag != nil {
	fmt.Printf("Output: %s\n", flag.Value.String())
	fmt.Printf("Was changed: %v\n", flag.Changed)
	fmt.Printf("Default: %s\n", flag.DefValue)
}

ShorthandLookup

func ShorthandLookup(name string) *Flag

Return the Flag structure of the short-handed flag, or nil if none exists. Panics if len(name) > 1.

Usage:

pflag.StringP("output", "o", "out.txt", "output file")
pflag.Parse()

flag := pflag.ShorthandLookup("o")
if flag != nil {
	fmt.Printf("Found flag by shorthand: %s\n", flag.Name)  // Prints: output
}

Programmatic Flag Setting

Set

func Set(name, value string) error

Set the value of the named command-line flag. Can be called before or after parsing.

Usage:

pflag.Int("port", 8080, "server port")
pflag.String("host", "localhost", "server host")

// Set defaults programmatically
pflag.Set("port", "9090")
pflag.Set("host", "0.0.0.0")

pflag.Parse()  // Command-line values override programmatic values

// Or set after parsing for dynamic configuration
pflag.Parse()
if needsReset {
	pflag.Set("port", "3000")
}

Checking Parse State

Parsed

func Parsed() bool

Return true if the command-line flags have been parsed.

Usage:

func getConfig() string {
	if !pflag.Parsed() {
		pflag.Parse()
	}
	config, _ := pflag.GetString("config")
	return config
}

Argument Access

After parsing, non-flag arguments can be accessed using Args functions.

Args

func Args() []string

Return the non-flag command-line arguments remaining after parsing.

Usage:

pflag.BoolP("verbose", "v", false, "verbose output")
pflag.Parse()

// Command line: myapp -v file1.txt file2.txt file3.txt
files := pflag.Args()  // []string{"file1.txt", "file2.txt", "file3.txt"}

for _, file := range files {
	fmt.Printf("Processing: %s\n", file)
}

Arg

func Arg(i int) string

Return the i'th command-line argument. Arg(0) is the first remaining argument after flags have been processed.

Usage:

pflag.Parse()

if pflag.NArg() >= 2 {
	source := pflag.Arg(0)
	dest := pflag.Arg(1)
	fmt.Printf("Copying %s to %s\n", source, dest)
}

NArg

func NArg() int

Return the number of arguments remaining after flags have been processed.

Usage:

pflag.Parse()

if pflag.NArg() == 0 {
	fmt.Fprintln(os.Stderr, "Error: no input files specified")
	os.Exit(1)
}

fmt.Printf("Processing %d files\n", pflag.NArg())

NFlag

func NFlag() int

Return the number of command-line flags that have been set.

Usage:

pflag.Parse()

if pflag.NFlag() == 0 {
	fmt.Println("No flags specified, using all defaults")
}

fmt.Printf("%d flags were set\n", pflag.NFlag())

Iterating Over Flags

Visit

func Visit(fn func(*Flag))

Visit the command-line flags in lexicographical order (or primordial order if SortFlags is false), calling fn for each. Visits only flags that have been set.

Usage:

pflag.String("output", "out.txt", "output file")
pflag.BoolP("verbose", "v", false, "verbose mode")
pflag.Int("count", 1, "iteration count")

pflag.Parse()

fmt.Println("Flags that were set:")
pflag.Visit(func(flag *pflag.Flag) {
	fmt.Printf("  --%s = %s\n", flag.Name, flag.Value.String())
})

VisitAll

func VisitAll(fn func(*Flag))

Visit the command-line flags in lexicographical order (or primordial order if SortFlags is false), calling fn for each. Visits all flags, even those not set.

Usage:

fmt.Println("All defined flags:")
pflag.VisitAll(func(flag *pflag.Flag) {
	status := "default"
	if flag.Changed {
		status = "set"
	}
	fmt.Printf("  --%s = %s (%s)\n", flag.Name, flag.Value.String(), status)
})

Direct Value Access via Flag Struct

When you have a Flag reference, you can access its fields directly:

type Flag struct {
	Name                string              // Flag name
	Shorthand           string              // One-letter abbreviation
	Usage               string              // Help message
	Value               Value               // Current value
	DefValue            string              // Default value as text
	Changed             bool                // Whether user set the value
	NoOptDefVal         string              // Default when flag present without value
	Deprecated          string              // Deprecation message
	Hidden              bool                // Hidden from help
	ShorthandDeprecated string              // Shorthand deprecation message
	Annotations         map[string][]string // Metadata for bash completion
}

Usage:

pflag.IntP("port", "p", 8080, "server port")
pflag.Parse()

portFlag := pflag.Lookup("port")
if portFlag != nil {
	fmt.Printf("Name: %s\n", portFlag.Name)
	fmt.Printf("Shorthand: %s\n", portFlag.Shorthand)
	fmt.Printf("Value: %s\n", portFlag.Value.String())
	fmt.Printf("Default: %s\n", portFlag.DefValue)
	fmt.Printf("Changed: %v\n", portFlag.Changed)
	fmt.Printf("Usage: %s\n", portFlag.Usage)

	if portFlag.Deprecated != "" {
		fmt.Printf("Deprecated: %s\n", portFlag.Deprecated)
	}
}

Value Interface

The Value field implements the Value interface for custom operations:

type Value interface {
	String() string       // Return string representation
	Set(string) error     // Parse and set value from string
	Type() string         // Return type name
}

Usage:

pflag.StringSlice("tags", []string{}, "tags to apply")
pflag.Parse()

tagsFlag := pflag.Lookup("tags")
if tagsFlag != nil {
	// Get current value
	current := tagsFlag.Value.String()
	fmt.Printf("Current tags: %s\n", current)

	// Get type
	fmt.Printf("Type: %s\n", tagsFlag.Value.Type())

	// Modify value programmatically
	err := tagsFlag.Value.Set("newtag1,newtag2")
	if err != nil {
		fmt.Printf("Error setting value: %v\n", err)
	}
}

SliceValue Interface

Slice-type flags also implement the SliceValue interface for advanced list operations:

type SliceValue interface {
	Append(string) error    // Add value to end
	Replace([]string) error // Replace all values
	GetSlice() []string     // Get all values
}

Usage:

pflag.StringSlice("files", []string{}, "files to process")
pflag.Parse()

filesFlag := pflag.Lookup("files")
if filesFlag != nil {
	if sv, ok := filesFlag.Value.(pflag.SliceValue); ok {
		// Get current slice
		current := sv.GetSlice()
		fmt.Printf("Current files: %v\n", current)

		// Append new value
		sv.Append("newfile.txt")

		// Replace all values
		sv.Replace([]string{"file1.txt", "file2.txt", "file3.txt"})
	}
}

Checking if Flag Exists

Before accessing a flag, you can check if it exists:

func flagExists(name string) bool {
	return pflag.Lookup(name) != nil
}

// Usage
if flagExists("debug") {
	debug, _ := pflag.GetBool("debug")
	fmt.Printf("Debug mode: %v\n", debug)
}

Handling Missing Flags

When accessing flags that might not exist, handle nil returns appropriately:

pflag.Parse()

// Safe access pattern
if flag := pflag.Lookup("optional-flag"); flag != nil {
	fmt.Printf("Optional flag value: %s\n", flag.Value.String())
} else {
	fmt.Println("Optional flag not defined")
}

// Or use Changed to check if flag was set
if pflag.Changed("optional-flag") {
	value, _ := pflag.GetString("optional-flag")
	fmt.Printf("User provided: %s\n", value)
} else {
	fmt.Println("Using default or flag not defined")
}

Complete Access Example

Here's a complete example demonstrating various access patterns:

package main

import (
	"fmt"
	"os"
	"github.com/spf13/pflag"
)

func main() {
	// Define flags
	port := pflag.IntP("port", "p", 8080, "server port")
	host := pflag.String("host", "localhost", "server host")
	tags := pflag.StringSlice("tag", []string{}, "tags")
	verbose := pflag.BoolP("verbose", "v", false, "verbose mode")

	pflag.Parse()

	// Access via pointers
	fmt.Printf("Server will run on %s:%d\n", *host, *port)

	// Check if flag was changed
	if pflag.Changed("port") {
		fmt.Println("Port was explicitly set")
	}

	// Access via Lookup
	if tagsFlag := pflag.Lookup("tag"); tagsFlag != nil && tagsFlag.Changed {
		fmt.Printf("Tags: %s\n", tagsFlag.Value.String())
	}

	// Iterate over set flags
	if *verbose {
		fmt.Println("\nFlags that were set:")
		pflag.Visit(func(flag *pflag.Flag) {
			fmt.Printf("  --%s: %s\n", flag.Name, flag.Value.String())
		})
	}

	// Access arguments
	files := pflag.Args()
	if len(files) == 0 {
		fmt.Fprintln(os.Stderr, "Error: no input files")
		os.Exit(1)
	}

	fmt.Printf("\nProcessing %d files:\n", pflag.NArg())
	for i, file := range files {
		fmt.Printf("  %d: %s\n", i+1, file)
	}
}