Thursday, September 29, 2016

Golang flag package demystified

Command line handling is an important part for CUI based applications. Almost every modern programming language offers some way to handle command line arguments with ease.

Like every modern programming language, Golang also offers a package called “flag” to handle command line arguments. Lets dive into the details of flag package.

The main and most important concept in flag package is something called FlagSet.

What is FlagSet:

If we consider our application name as a command then FlagSet represents a subcommand with flags associated with it or in other way every subcommand can be implemented using a separate FlagSet. Check the below git syntax.
user add <username>
user remove -d <username>
Here in above syntax git is a main application with two subcommands called “add” and “commit”. Subcommand “add” doesn’t have any flag associated with it but “commit” has a flag “m” which modifies the behavior of subcommand.

Internally FlagSet is a struct type with methods to manage flags of various types. Check its documentation at
In flag package a function “NewFlagSet” available which has the following syntax.
NewFlagSet(name, errorhandlingbehavior)
In above syntax, first argument is name of flag in string format. Second argument is one of the constants from flag package to define error handling behavior.

flag.ContinueOnError - Application continues parsing of arguments even if error is encountered
flag.ExitOnError - Application exits with status code 2 on parsing error
flag.PanicOnError - Application panics on parsing error

You can see these constants define at

The method returns a pointer to a newly created variable of FlagSet type which can then be used to define flags. To add new flag, FlagSet struct has a method for various Golang types. One of them used to define int flag is described below.
Int(name string, value int, usage string) *int
This method defines an int flag. The first argument defines name of flag, second defines a default value and third defines a usage string for flag. It returns the address of an int variable that stores the value of flag.

There are similar methods for other types too. Checkout flag package documentation at for exhaustive list.

Now after understanding FlagSet and a way to add flags, we can create FlagSet.
addCommand := flag.NewFlagSet("add", flag.ExitOnError)
userName := addCommand.String("name", "", "Name of user")

removeCommand := flag.NewFlagSet("remove", flag.ExitOnError)
removeDirectory := removeCommand.Bool("d", false, "Remove home directory of a user")
In above snippet, we are creating two FlagSets addCommand and removeCommand. addCommand has a string flag called username and removeCommand has a Boolean flag called d.

After creating FlagSets we need to check that user has entered sufficient arguments using the following snippet.
    if len(os.Args) < 2 {
                    fmt.Println("Not sufficient arguments")

Now we have to check for entered subcommand. We will use switch case here.
       switch os.Args[1] {
        case "add":

        case "remove":

                fmt.Println("No Command parsed")
In above code, we are calling a method Parse() of FlagSet if the command is entered. Parse() method actually parses the command line argument that we have in os.Args array. We are passing arguments from index 2 to the end of array because first argument is always name of executable program and second argument is our subcommand.

Next we need to check if subcommands are parsed. If any one of them parsed then we have to initiate some action related to it.
       if addCommand.Parsed() {
                fmt.Println("add subcommand entered")
                if *userName != "" {
                        fmt.Println("Username:", *userName)
                } else {
                        fmt.Println("No username entered")

        if removeCommand.Parsed() {
                fmt.Println("remove subcommand entered")
                if *removeDirectory == true {
                        fmt.Println("Home directory of user is removed")
                } else {
                        fmt.Println("Home directory of user is not removed")
Parsed() method returns boolean value based on parsing status of FlagSet.

In this way, flag package can be used to handle command line arguments in Golang applications.

flag package contains some methods which are actually wrapper on FlagSet methods. Like we can directly call flag.Int() to define int flag. These methods internally uses a default FlagSet.

You can find complete example at

No comments:

Post a Comment