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)$ ./serve -addr :9000 -workers 8 -v
:9000 8 trueAnything left after the flags is a positional argument. Parsing stops at the first one, so flags have to come first.
flag.Parse()
if flag.NArg() != 1 {
flag.Usage()
os.Exit(2)
}
dir := flag.Arg(0)
fmt.Println(dir, flag.NArg())$ ./serve -v ./public
./public 1Var takes anything with String and Set. Set runs once per occurrence, so appending inside it gives you a flag that can be passed more than once.
type tags []string
func (t *tags) String() string { return strings.Join(*t, ",") }
func (t *tags) Set(v string) error {
*t = append(*t, v)
return nil
}
var list tags
flag.Var(&list, "tag", "tag to apply, repeatable")
flag.Parse()$ ./serve -tag api -tag beta ./public
api,betaA FlagSet is an independent group of flags. Give each subcommand its own set and parse it against the arguments after the subcommand name.
serveCmd := flag.NewFlagSet("serve", flag.ExitOnError)
addr := serveCmd.String("addr", ":8080", "listen address")
initCmd := flag.NewFlagSet("init", flag.ExitOnError)
force := initCmd.Bool("force", false, "overwrite existing files")
if len(os.Args) < 2 {
fmt.Println("expected a subcommand")
os.Exit(2)
}
switch os.Args[1] {
case "serve":
serveCmd.Parse(os.Args[2:])
fmt.Println("serving on", *addr)
case "init":
initCmd.Parse(os.Args[2:])
fmt.Println("init, force =", *force)
}$ ./tool serve -addr :9000
serving on :9000
$ ./tool init -force
init, force = true| Function | Description |
|---|---|
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. |
Every | |
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. |
A bool flag is set by being present. Giving it a value needs an equals sign, because a space would look like a positional argument. | |
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. |
Duration flags go through | |
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. |
Implement | |
Parse() | Parses the command line. Every flag must be defined before this runs. |
Defining a flag after | |
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. |
A | |
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.
$ 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 1Run 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.
$ ./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)