How to use the Flag Package in Go

The flag package is a built-in package in Go that provides a way to define and parse command-line flags. Command-line flags are a common way for command-line programs to specify options and arguments.

Import the package

To get started with the flag package, you will first need to import it in your Go program:

import "flag"

Parsing flags

The flag package defines a FlagSet type that you can use to define and parse flags. The FlagSet type has several methods that you can use to define new flags, such as String, Int, and Bool. Here's an example of how to define a new flag named name that is a string flag:

var name string
flag.StringVar(&name, "name", "default value", "help message")

In this example, we create a variable name of type string and associate it with the flag. The second argument to the StringVar function is the name of the flag, the third argument is the default value, and the fourth argument is a help message that will be displayed when the program is run with the -h or --help flag.

You can also use flag.String and flag.StringVar functions, here is an example:

name := flag.String("name", "default value", "help message")

Once you've defined your flags, you can parse them by calling the flag.Parse() function. This function will look at the command-line arguments passed to your program and set the values of the flags accordingly.

Here is an example that defines two flags and then parses them:

package main

import (
    "flag"
    "fmt"
)

func main() {
    var name string
    flag.StringVar(&name, "name", "default value", "help message")

    var age int
    flag.IntVar(&age, "age", 18, "help message")

    flag.Parse()
    fmt.Println("Name:", name)
    fmt.Println("Age:", age)
}

In this example, we first defined two flags, one for name and the other for age, with their default values and help message. And then we parse the flags and print the values.

You can now run this program with the -name and -age flags set to the values you want, like this:

$ go run main.go -name="John Doe" -age=30

When this program is run, the name variable will be set to "John Doe" and the age variable will be set to 30.

The number of flags that where used in the program call are accessible via the flag.NFlag() function.

Parsing arguments

After you have defined and parsed your flags you can use the flag.Args() function o access any remaining command-line arguments that were not parsed as flags.

For example, consider the following program that defines a flag named file and then uses the Args() function to access any remaining arguments:

package main

import (
    "flag"
    "fmt"
)

func main() {
    var file string
    flag.StringVar(&file, "file", "", "file to process")
    flag.Parse()
    fmt.Println("File:", file)
    fmt.Println("Other arguments:", flag.Args())
}

In this example, the program defines a file flag that is used to specify the file that should be processed. After the flags are parsed, the program uses the Args() function to access any remaining arguments that were not parsed as flags.

If you run the above program like this:

$ go run main.go -file=main.go arg1 arg2

The output will be:

File: main.go
Other arguments: [arg1 arg2]

As you can see, the program correctly sets the value of the file flag to "main.go", and the remaining arguments "arg1" and "arg2" can be accessed using flag.Args().

Single arguments can be accessed by passing an index to the function.

In addition, it's also possible to use flag.NArg() to find out how many arguments are left after flags are parsed.

Parsing flags the GNU way

One downside that I found with this package is that it does not use GNU parsing rules. This results in the fact that e.g. when a non-flag argument is passed to the program all following flag arguments will not be parsed by the flag.Parse() function.

A solution to this problem is using the gnuflag package instead.