The flag package in Golang

Flags are an important aspect of CLI applications. They are provided while running the program so that the program runs with the correct parameters. In this post, we will explore the flag package and what it offers.

What are the flags?

When we run a program, we can pass various parameters to the executable. If we take an example command like this:

./program -a=b -c=d

The flags are a & c and the values of the flags are b & d respectively.

Creation of flags in Golang

Here is an example showing the usage of the flags as well as how to create one.

package main

import (
	"flag"
	"fmt"
)

func main() {
	// a program that takes two numbers and return roduct

        // declare variables
        // in this case two integers
	var a, b int

        // set a and b as flag int vars
	flag.IntVar(&a, "a", 1, "The first number! Default is 1")
	flag.IntVar(&b, "b", 1, "The second number! Default is 1")

        // parse flags from command line
	flag.Parse()
 
        // output
	fmt.Println(a * b)
}

Now, the signature of the flag intvar is:

flag.IntVar(pointer to var, command line name, default value, description)

Now, to see what these flag variables do we can get help from the CLI by passing the -h flag.

./application -h

Here in our case, the output is:

Go Help Flag
Go Help Flag

So, now we can try passing flags and test our program.

We will run the following command:

go run filename.go -a=12 -b=21

The output is 252 as expected.

Usage of different Golang flags

Here is the sample usage of the flags that can be created using flag functions. Also worth noting, the difference between the var and nonvar functions when creating different flags. The difference is that the var function takes in a pointer and stores the flag there, whereas, the non-var ones return a pointer that can be stored and used.

Here is a sample argument example that can be passed via the CLI.

-anint=42
-afloat=2.3
-astring=hello   // no need for ""
-aboolean        // true
-aboolean=false  // false

Creating subcommands

Subcommands can be seen in sophisticated CLI tools like git. Some git subcommands are:

git commit -m ...
git merge ...
git pull  ... 

Commit, merge, pull, etc are all subcommand of git. The flag package allows for the creation of subcommand using flagsets.

Now, we will create a basic calc CLI tool that will add and multiply two numbers.

package main

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

func main() {
	addcmd := flag.NewFlagSet("add", flag.ExitOnError)
	a_add := addcmd.Int("a", 0, "The value of a")
	b_add := addcmd.Int("b", 0, "The value of b")

	mulcmd := flag.NewFlagSet("mul", flag.ExitOnError)
	a_mul := mulcmd.Int("a", 0, "The value of a")
	b_mul := mulcmd.Int("b", 0, "The value of b")

	switch os.Args[1] {
	case "add":
		addcmd.Parse(os.Args[2:])
		fmt.Println(*a_add + *b_add)
	case "mul":
		mulcmd.Parse(os.Args[2:])
		fmt.Println(*(a_mul) * (*b_mul))
	default:
		fmt.Println("expected add or mul command")
		os.Exit(1)
	}
}

Now to run this CLI functions here are sample inputs for running:

go run filename.go add -a=42 -b=23
go run filename.go mul -a=25 -b=4

When run this we get:

Go Flagset Add
Go Flagset Add
Go Flagset Mul
Go Flagset Mul

Uses of the flag package

The flag package is mainly used for creating CLI tools as it makes it a lot easy, as can be seen already. This package is a very versatile yet very focused one with a very specific usage.