paulgorman.org/technical

Go Flag and FlagSet

Go provides a flag package to handle command-line flags.

Go flags vary slightly from traditional unix flags. Go has no “short” and “long” flags differentiated by one or two dashes. -debug is the same as --debug, and the three options -a -d -v may not be written -adv. Giving values to flags works like -level=2 or -level 2 (except that boolean values must use the = form to avoid ambiguity with shell wildcards).

Flag parsing stops just before the first non-flag argument (- is a non-flag argument) or after the terminator --.

Specify one or more flag variables, then call flag.Parse().

import "flag"

var ip = flag.Int("flagname", 1234, "help message for flagname")

func init() {
	flag.Parse()
	fmt.Println(*ip)
}

…or:

var flagvar int

func init() {
	flag.IntVar(&flagvar, "flagname", 1234, "help message for flagname")
	flag.Parse()
	fmt.Println(flagvar)
}

FlagSet

The FlagSet types enables subcommands (e.g., git log or ip address show).

package main

import (
	"flag"
	"fmt"
	"os"
)

func main() {
	var a, b, y, z string

	// Set of flags for subcommand 1
	fs1 := flag.NewFlagSet("fs1", flag.ExitOnError)
	fs1.StringVar(&a, "a", "foo", "subcommand 1 flag 'a'")
	fs1.StringVar(&b, "b", "bar", "subcommand 1 flag 'b'")

	// Set of flags for subcommand 2
	fs2 := flag.NewFlagSet("fs2", flag.ExitOnError)
	fs2.StringVar(&y, "y", "foo", "subcommand 2 flag 'y'")
	fs2.StringVar(&z, "z", "bar", "subcommand 2 flag 'z'")

	help := "Add the subcommand 'edit' or 'list'!"

	// Switch on subcommands, then apply the desired set of flags.
	if len(os.Args) < 2 {
		fmt.Fprintln(os.Stderr, help)
		os.Exit(0)
	}
	switch os.Args[1] {
	case "edit":
		if err := fs1.Parse(os.Args[2:]); err == nil {
			fmt.Println("edit", a)
		}
	case "list":
		if err := fs2.Parse(os.Args[2:]); err == nil {
			fmt.Println("list", z)
		}
	default:
		fmt.Fprintln(os.Stderr, help)
		os.Exit(0)
	}
}