Reading command line arguments is a common use case for both CLI and API applications - Go makes this very easy to do using just the standard library via the flag package. Let's see how.

A Comprehensive Guide to the Flag Package


Reading command line arguments is a common use case for both CLI and API applications - Go makes this very easy to do using just the standard library via the flag package. Let’s see how.

The flag package provides the ability to read command line arguments (or flags). It supports reading various data types, including strings, integers, and booleans, making it versatile for different kinds of applications.

Simple Flag Package Usage

Here’s the “hello world” for the Go flag package.

package main

import (
"flag"
"fmt"
)

func main() {
name := flag.String("name", "World", "a name to say hello to")
flag.Parse()
fmt.Printf("Hello, %s!n", *name)
}

and we run it like this:

go run main.go -name=Gopher

and it outputs:

Hello, Gopher!

If we don’t pass an argument in for this flag, it will default to the value “world” and print this:

Hello World

you can try it yourself on the Go playground.

Using Different Flag Types

Integer Flags

port := flag.Int("port", 8080, "port number")

Boolean Flags

verbose := flag.Bool("verbose", false, "enable verbose mode")

and you can parse them like this:

flag.Parse()
fmt.Println("Port:", *port)
fmt.Println("Verbose Mode:", *verbose)

You can play with this example here.

Custom Flag Parsing

You can customize flag parsing too!

flag.Var

For custom flag types, implement the flag.Value interface:

type arrayFlags []string

func (i *arrayFlags) String() string {
    return fmt.Sprintf("%v", *i)
}

func (i *arrayFlags) Set(value string) error {
    *i = append(*i, value)
    return nil
}

var languages arrayFlags

func main() {
    flag.Var(&languages, "lang", "language options")
    flag.Parse()
    fmt.Println("Languages:", languages)
}

You run it like this:

go run main.go -lang=Go -lang=Python

and you get the output:

Languages: [Go Python]

This one doesn’t work so well in the playground, but you can see the full code here and it still executes.

Using Flag Sets

The flag package allows the creation of custom FlagSet objects, useful for parsing flags from different sources or for subcommands.

fs := flag.NewFlagSet("ExampleFlagSet", flag.ExitOnError)

message := fs.String("message", "default", "a message")
fs.Parse([]string{"-message", "Hello FlagSet"})

fmt.Println("Message:", *message)

outputs:

Message: Hello FlagSet

You can try this on the playground here.

Rules to Remember when working with Flags in Go

  • Always Call flag.Parse(); Ensure you parse the flags before using them.
  • Check for Required Flags: Manually verify if mandatory flags are provided.
  • Use Meaningful Flag Names!

Wrapping Up

The flag package has a small API, and it really is possible to learn it all! Check it out here.

Some Gopher’s opt to use libraries. We cover all of that and much much more in our course on developing CLI applications. Check it out here.