HowtoGo
Home / Standard Library / The flag Package
Standard Library

The flag Package

flag parses command-line options with no dependencies and no struct tags. Define each flag, call Parse, read the values. See A complete CLI below for the whole thing in one program.

Examples

Three steps, always in that order. Every flag has to be defined before Parse runs, and no value is populated until it does.

addr := flag.String("addr", ":8080", "listen address")
workers := flag.Int("workers", 4, "number of workers")
verbose := flag.Bool("v", false, "verbose logging")

flag.Parse()

fmt.Println(*addr, *workers, *verbose)
Output
$ ./serve -addr :9000 -workers 8 -v
:9000 8 true
FunctionDescription
String(name string, value string, usage string) *string
addr := flag.String("addr", ":8080", "listen address")
Defines a string flag and returns a pointer to where the value will land.
Int(name string, value int, usage string) *int
Defines an int flag. Non-numeric input fails the parse and prints usage.
Bool(name string, value bool, usage string) *bool
Defines a bool flag. Present means true, so -v needs no value.
Float64(name string, value float64, usage string) *float64
Defines a float flag.
Duration(name string, value time.Duration, usage string) *time.Duration
-timeout 5s
Defines a duration flag, parsed with time.ParseDuration.
StringVar(p *string, name string, value string, usage string)
Same as String, but writes into a variable you already have instead of returning a pointer.
Var(value Value, name string, usage string)
Defines a flag backed by your own type, which is how repeatable and custom flags are built.
Parse()
Parses the command line. Every flag must be defined before this runs.
Parsed() bool
Reports whether Parse has been called.
Args() []string
The non-flag arguments left after parsing.
Arg(i int) string
One positional argument by index. Returns "" when out of range.
NArg() int
if flag.NArg() != 1 { flag.Usage(); os.Exit(2) }
How many positional arguments are left.
NFlag() int
How many flags were actually set on the command line.
Usage
A function value printed on a parse error or -h. Replace it to control the help text.
PrintDefaults()
Prints every defined flag with its type, usage string, and default.
NewFlagSet(name string, errorHandling ErrorHandling) *FlagSet
An independent set of flags, which is how subcommands are built.
type Value interface
String() string and Set(string) error. Implement both and Var accepts your type.
ErrorHandling
ContinueOnError, ExitOnError, or PanicOnError. The package-level CommandLine set uses ExitOnError.

A complete CLI

Every function in the table above, in one program: typed flags, a repeatable custom flag, a positional argument, and a replaced usage message.

main.go 56 lines Show
package main

import (
	"errors"
	"flag"
	"fmt"
	"os"
	"strings"
	"time"
)

// A repeatable flag: -tag a -tag b
type tags []string

func (t *tags) String() string     { return strings.Join(*t, ",") }
func (t *tags) Set(v string) error {
	if v == "" {
		return errors.New("tag must not be empty")
	}
	*t = append(*t, v)
	return nil
}

func main() {
	var (
		addr    = flag.String("addr", ":8080", "address to listen on")
		workers = flag.Int("workers", 4, "number of workers")
		verbose = flag.Bool("v", false, "verbose logging")
		timeout = flag.Duration("timeout", 30*time.Second, "request timeout")
		ratio   = flag.Float64("ratio", 0.5, "sampling ratio")
		list    tags
	)
	flag.Var(&list, "tag", "tag to apply, repeatable")

	flag.Usage = func() {
		fmt.Fprintf(flag.CommandLine.Output(), "usage: serve [options] <dir>\n\n")
		flag.PrintDefaults()
	}

	flag.Parse()

	if flag.NArg() != 1 {
		flag.Usage()
		os.Exit(2)
	}

	fmt.Println("dir     ", flag.Arg(0))
	fmt.Println("addr    ", *addr)
	fmt.Println("workers ", *workers)
	fmt.Println("verbose ", *verbose)
	fmt.Println("timeout ", *timeout)
	fmt.Println("ratio   ", *ratio)
	fmt.Println("tags    ", list.String())
	fmt.Println("NArg    ", flag.NArg())
}

Flags can appear in any order and stop at the first non-flag argument, which is why ./public has to come last.

-ratio was never passed, so it holds the default the definition gave it.

Terminal
$ go build -o serve .
$ ./serve -addr :9000 -workers 8 -v -timeout 5s -tag api -tag beta ./public
dir      ./public
addr     :9000
workers  8
verbose  true
timeout  5s
ratio    0.5
tags     api,beta
NArg     1

Run with no arguments and the replaced Usage prints, followed by PrintDefaults.

Each line shows the flag's type and default. A bool prints on one line because it takes no value, and a custom type shows as value.

Terminal
$ ./serve
usage: serve [options] <dir>

  -addr string
        address to listen on (default ":8080")
  -ratio float
        sampling ratio (default 0.5)
  -tag value
        tag to apply, repeatable
  -timeout duration
        request timeout (default 30s)
  -v    verbose logging
  -workers int
        number of workers (default 4)
Related: os strconv time