Exploring Go Packages: Argparse

In this tutorial, we walk through what Argparse is and how to build a command-line interface with this package.

Jane Kozhevnikova
Level Up Coding

--

A picture of mine

› Shortly about Argparse

Argparse is a command-line parser for Go. The package automatically generates a help message without predefining it. You probably have heard about Argparse for Python. It brings some features to the Argparse package for Go.

› Before You Begin

Install the package to your computer:

go get -u -v github.com/akamensky/argparse

The -u flag instructs go get to use the network to update the named packages and their dependencies. By default, get uses the network to check out missing packages but does not use it to look for updates to existing packages.

The -v flag enables verbose progress and debug output.

See this resource to learn more about the go get command.

Import the package in your *.go file as follows:

import “github.com/akamensky/argparse”

› Writing Help Message

A help message (or usage message, or doc) is what users see when they

  • invoke a program,
  • type a flag like --hor -h,
  • type invalid arguments.

This message includes the name of the program, its usage, and options. If you use the command line, you are already familiar with help messages or usage messages. In Linux, you can usually type program --helpto get a list of acceptable arguments of the program.

In this tutorial, we write a help message for a program that outputs:

  • a list of random numbers of a specified count and range, or
  • a list of random letters of a specific count and language.

This is our usage message:

Let’s analyze a command, numbers, from the preceding message:

randx numbers --count <count> [--range <range>...]

  • randx — a name of the program,
  • numbers — a command,
  • --count— an option of the command,
  • <count> — a value of the option — count,
  • [--range <range>…] — an optional parameter which requires a value or several values,
  • [--verbose]— an optional flag.

We have two commands, numbers and letters (bool), to enable the numbers or letters mode, respectively. If one of them is true, another is false.

The — count(int) option is required for both the numbers andletters commands. The program outputs a list of numbers or letters of the specified count.

$ randx numbers --count 1

$ randx letters --count 1

To declare an optional argument --range([]string), we use square brackets. Three dots in the square brackets mean that you can pass several arguments to the command prompt. For example,

- — range 1,10 --range 1,11 or
--range 1-10 --range 1-11 or
--range 1:10 --range 1:11

This option sets a range of random numbers. If there are two arguments, the program outputs two lists with the specified ranges.

The optional argument, --lang (string), is also in square brackets. The option accepts a language. Therefore the program outputs letters of the specified language.

The program must return a help message when the required option is not set and/or the arguments are invalid. Both --range and --lang options can be omitted.

Also, we have three options (or just flags) without operands in the usage message:

  • -h / --help — output the usage message,
  • --verboseoutput the details of what a program does; the flag is used to inform a user what the program actually does, including errors while performing a required action. This can be helpful for troubleshooting problems.
  • --version — output the version of the program which you use.

› Writing Code

We will code the preceding usage message with the package’s methods only. Argparse automatically generates your doc according to the called methods and given information.

There is no need to define the help message in the code. But I recommend keeping it in front of your eyes. I suggest creating a variable usageat the beginning of a *.go file, and storing the help message there to eliminate confusion and mistakes during coding.

Create a parser with the method argparse.NewParser() in main(). There are two parameters in the method: the name of the program and its description. They will both be displayed in the usage message.

parser := argparse.NewParser("randx", "Returns random numbers or letters")

Declare the commands, lettersand numbers, with a parser.NewCommand() method. This method accepts the name of command and description. This information will be displayed in the help message as well.

commandNumbers := parser.NewCommand("numbers", "Returns random numbers")commandLetters := parser.NewCommand("letters", "Returns random letters")

The--verboseflag (bool) must be available for all commands. Therefore, we need to make it accessible for letters and numbers. To achieve this, create a
--verbose flag with parser.Flag()method.

verbose := parser.Flag(
"", "verbose", &argparse.Options{
Help: "Verbose mode",
},
)

The --version flag (bool) is declared in the same way as --verbose:

version := parser.Flag(
"v", "version", &argparse.Options{
Help: "Current version",
},
)

Then, we create the required options and non-required options. All of them are declared in a common pattern:

option := command.Type_of_option(
“short_name”, ”long_name”, &argparse.Options{
Required: true/false,
Help: “description_of_an_option”,
},
}

Declare --count option for numbers command:

countNumbers := commandNumbers.Int(
"c", "count", &argparse.Options{
Required: true,
Help: "Count of random numbers",
},
)

Declare --rangeoption for numbers command:

rangeNumbers := commandNumbers.List(
"r", "range", &argparse.Options{
Help: "Gives numbers of specific range",
},
)

Declare --count option for letters command:

countLetters := commandLetters.Int(
"c", "count", &argparse.Options{
Required: true,
Help: "Count of random letters",
},
)

Declare --lang option for letterscommand:

langLetters := commandLetters.String(
"l", "lang", &argparse.Options{
Help: "Specifies a language",
},
)

Parse all the given arguments:

err := parser.Parse(os.Args)
if err != nil {
log.Fatalln(parser.Usage(err))
return
}

To print values of different commands, use switchand fmt.Println():

switch {
case commandNumbers.Happened():
fmt.Println("numbers:", commandNumbers.Happened())
fmt.Println("--count:", *countNumbers)
fmt.Println("--range:", *rangeNumbers)
fmt.Println("--verbose:", *verbose)
case commandLetters.Happened():
fmt.Println("letters:", commandLetters.Happened())
fmt.Println("--count:", *countLetters)
fmt.Println("--lang:", *langLetters)
fmt.Println("--verbose:", *verbose)
...

We have already declared the flag --version. However, to display a version when this flag is true, use this code:

...
case *version:
fmt.Println("version_is_here")
}

› Usage

In this section, you can find several cases of how to use Argparse in the command line.

›› Letters Mode

$ go run main.go letters --count 9 
$ go run main.go letters -c 9
letters: true
--count: 9
--lang:
--verbose: false
$ go run main.go letters --count 9 --lang en
$ go run main.go letters -c 9 -l en
letters: true
--count: 9
--lang: en
--verbose: false

›› Numbers Mode

$ go run main.go numbers --count 9 
$ go run main.go numbers -c 9
numbers: true
--count: 9
--range: []
--verbose: false
$ go run main.go numbers --count 10 --range 9,10
$ go run main.go numbers -c 10 -r 9,10
numbers: true
--count: 10
--range: [9,10]
--verbose: false
$ go run main.go numbers --count 10 --range 9,10 --range 0,15
numbers: true
--count: 10
--range: [9,10 0,15]
--verbose: false

›› Verbose

$ go run main.go numbers --count 18 --range 9,19 --verbose 
$ go run main.go numbers -c 18 -r 9,19 --verbose
numbers: true
--count: 18
--range: [9,19]
--verbose: true

› About Author

Jane is a Go programmer and technical writer in software engineering. She has been writing technical material for 5 years in both English and Russian. She completed her specialist degree in Information Security from Novosibirsk State Technical University, and specializes in the information security of automated systems. You can follow her on Twitter and see her other written work at publications.enthusiastic.io.

--

--