Adding Command Line Flags to Your Go App

Command line flags are really easy to add to your application, I’ll quickly run through two techniques that should get you going in the right direction. The first:

package main

import (
	"flag"
	"fmt"
)

type Config struct {
	age    int
	name   string
	hungry bool
}

var config Config

func main() {
	// Map the flags to variables.
	flag.IntVar(&config.age, "age", 4543000000, "user age")
	flag.StringVar(&config.name, "name", "World", "user name")
	flag.BoolVar(&config.hungry, "hungry", true, "whether the user is hungry")

	// Parse the flags.
	flag.Parse()

	fmt.Printf("Name:   %s\n", config.name)
	fmt.Printf("Age:    %d\n", config.age)
	fmt.Printf("Hungry: %v\n", config.hungry)
	fmt.Printf("Other:  %v\n", flag.Args())
}

The flag package does most of the grunt work when you call Parse(). Before that though, the flags need to be described, which is done on these lines:

flag.IntVar(&flags.age, "age", 4543000000, "user age")
flag.StringVar(&flags.name, "name", "World", "user name")
flag.BoolVar(&flags.hungry, "hungry", true, "whether the user is hungry")

The majority of built in types will have a corresponding flag.<Type>Var(...) method that takes the following arguments:

  1. Address of a variable to store the flag value.
  2. Name of the flag as it will appear on the command line.
  3. Default value if it isn’t defined when the application is run.
  4. A description of what the flag is – to be displayed in the help page.

In this case I’ve opted to have a global object, config, and use that to store the values of all the flags.

Once that has been done, calling flag.Parse() will actually parse the command line arguments and populate the config object. If there are any more arguments that aren’t captured, they’ll become available as a slice accessible by calling flag.Args().

Here are a few examples of the output based on the flags used, note the default values.

$ ./goflags 

Name:   World
Age:    4543000000
Hungry: true
Other:  []

$ ./goflags -age 30 -name Bob

Name:   Bob
Age:    30
Hungry: true
Other:  []

$ ./goflags -age 26 -name Jess -hungry=false

Name:   Jess
Age:    26
Hungry: false
Other:  []

$ ./goflags -name="Two words" -age=50 -hungry=false extra args

Name:   Two words
Age:    50
Hungry: false
Other:  [extra args]

$ ./goflags -h

Usage of ./goflags:
  -age int
    	user age (default 4543000000)
  -hungry
    	whether the user is hungry (default true)
  -name string
    	user name (default "World")

A few things of note:

  • passing -h or –help will display a description of the available flags and default values.
  • flags can be passed in a number of ways, all the following are valid to set the name:
    • -name Bob
    • --name Bob
    • -name=Bob
    • --name="Bob"

The other common way I’ve seen flags being used is using the flag.<Type>(...) method, which will return a pointer to a location where the value will be stored. I find this a bit more round-about. I’ll include it here though as it is still commonly used:

package main

import (
	"flag"
	"fmt"
)

func main() {
	agePtr := flag.Int("age", 4543000000, "user age")
	namePtr := flag.String("name", "World", "user name")
	hungryPtr := flag.Bool("hungry", true, "whether the user is hungry")

	// Parse the flags.
	flag.Parse()

	fmt.Printf("Name:   %s\n", *namePtr)
	fmt.Printf("Age:    %d\n", *agePtr)
	fmt.Printf("Hungry: %v\n", *hungryPtr)
	fmt.Printf("Other:  %v\n", flag.Args())
}

If you build and run this you’ll see a similar output.

As always, if you want more info, check out the package documentation on the official Go site, here. Or post a comment below and I’ll answer as best i can.

Leave a Reply

Your email address will not be published. Required fields are marked *