Skip to main content

Command Palette

Search for a command to run...

Day 14 - Go Command Line Arguments

Published
5 min read

Command Line Arguments in Go

In Go, we can pass arguments to a program while running it from the terminal. These are called command-line arguments, and they can be accessed inside the main() function.

There are so many packes in go (in built and third party packages) to handle with command line arguments. Let us go through some methods.


1. Using os.Args

The simplest way to read command-line arguments is using the os.Args slice.

package main
import (
    "fmt"
    "os"
)

func main() {
    args := os.Args[:]
    fmt.Println("These are the list of args:", args)
}

Example Run

go run .\Day14\cmd.go "kalki" arg1

Output

These are the list of args [C:\Users\sivak\AppData\Local\Temp\go-build3819119338\b001\exe\cmd.exe kalki arg1]
  • You might notice 3 values:

    • The first element is always the executable path.
    • The rest are the actual arguments provided.

So, we usually skip the first element:

args := os.Args[1:]
fmt.Println(args)

Output

[kalki arg1]

2. Using the flag Package

For more structured and type-safe argument handling, Go provides the flag package. It allows you to define named parameters (called flags) with default values and help messages.

Key Features of flag

  • Type Safety: Supports string, int, bool, float64, etc.
  • Default Values: Used when the user doesn’t specify the flag.
  • Help Messages: Automatically generated (-h or --help).
  • Multiple Input Formats: e.g. -flag=value or -flag value.
  • Positional Args: Accessed using flag.Args() after parsing.

A. Returning a Pointer (flag.String())

package main

import (
    "flag"
    "fmt"
)

func main() {
    name := flag.String("name", "Guest", "The name to use in the greeting.")
    port := flag.Int("port", 8080, "The port number for the service.")

    flag.Parse()

    fmt.Printf("Hello, %s! Service running on port %d.\n", *name, *port)
}

Output

go run main.go -name="Alice" -port=9000
# Output: Hello, Alice! Service running on port 9000.

go run main.go
# Output: Hello, Guest! Service running on port 8080.

B. Binding to Existing Variables (flag.StringVar())

package main

import (
    "flag"
    "fmt"
)

func main() {
    var name string
    var debug bool

    flag.StringVar(&name, "name", "Guest", "Your name")
    flag.BoolVar(&debug, "debug", false, "Enable debug mode")

    flag.Parse()

    fmt.Printf("Hello, %s! Debug mode: %v\n", name, debug)
}

Advanced flag Features

  • Positional Arguments:

    extras := flag.Args()
    fmt.Println("Extra args:", extras)
    
  • Specific Index: flag.Arg(0) gives the first positional argument.

  • Custom Types: Implement flag.Value interface for custom data types.

  • Subcommands: Create new flag sets with flag.NewFlagSet().

  • Error Handling: Automatically handles invalid or missing flags.


3. For Complex CLIs → Use Cobra

For larger CLI applications (like git commit or go run), Go developers use the Cobra library.

Why Use Cobra?

  • Subcommands (mycli add, mycli delete, etc.)
  • Built-in help and usage docs
  • Auto-generated shell completion
  • Works with Viper for config files and environment variables

Installation

go get -u github.com/spf13/cobra@latest

Example: Basic Cobra CLI

package main

import (
    "fmt"
    "github.com/spf13/cobra"
)

func main() {
    var name string

    var rootCmd = &cobra.Command{
        Use:   "app",
        Short: "A simple CLI example using Cobra",
        Run: func(cmd *cobra.Command, args []string) {
            fmt.Printf("Hello, %s!\n", name)
        },
    }

    rootCmd.PersistentFlags().StringVarP(&name, "name", "n", "Guest", "Name of the user")
    rootCmd.Execute()
}

Example Run

go run main.go --name=John
# Output: Hello, John!

go run main.go -n Doe
# Output: Hello, Doe!

Cobra is especially useful when your CLI has multiple commands, such as:

myapp user add
myapp user list
myapp config set

Each command can have its own flags, description, and logic.


Why Command-Line Arguments Are Used?

Command-line arguments let you pass input values directly to a program when it starts running, rather than hardcoding them or using interactive input. They make your program flexible, configurable, and automation-friendly.


1. Configuration and Customization

Instead of modifying code or config files, users can control program behavior directly from the command line.

Example Use Case:

  • A web server can take flags for host and port:

    go run server.go --port=8080 --env=production
    

    → The program dynamically adjusts its behavior based on input.

Why Useful: Quickly switch between development, testing, and production modes.


2. File and Path Inputs

Programs often need to read data from or write output to specific files or directories.

Example Use Case:

go run converter.go input.csv output.json
  • The first argument is the input file.
  • The second argument is the output file.

Why Useful: Lets the same tool process multiple files without editing code every time.


3. Data Processing Tools

CLI arguments are commonly used in data or text processing utilities.

Example Use Case:

go run wordcount.go --file=sample.txt --ignore-case

Why Useful: Makes tools reusable for multiple datasets or with optional behavior changes (e.g., ignoring case).


4. Automation and Scripting

Command-line arguments allow programs to integrate easily into scripts and CI/CD pipelines.

Example Use Case:

./deploy.sh --region=us-east-1 --force

Why Useful: No manual input required — fully automatable and easy to integrate into deployment workflows.


5. Controlling Debug or Logging Levels

You can toggle debug or verbose modes dynamically.

Example Use Case:

go run app.go --debug

Why Useful: Developers can inspect logs without modifying source code.


6. Authentication and Credentials

Programs can accept secure tokens, API keys, or session credentials as arguments (carefully handled).

Example Use Case:

go run fetch.go --token=ABC123XYZ

Why Useful: Enables secure automation while keeping secrets external to code.


7. Environment Selection

Choosing environment-specific configuration (e.g., dev/test/prod).

Example Use Case:

go run app.go --env=staging

Why Useful: One program binary can serve multiple environments.


8. Arithmetic or Functional Inputs

Mathematical or functional utilities often take inputs as arguments.

Example Use Case:

go run calculator.go add 10 20
# Output: 30

Why Useful: Quick CLI utilities can compute or transform data instantly.


9. Subcommands (Advanced CLIs)

In complex tools (like git, docker, kubectl), arguments define which subcommand to run.

Example Use Case:

git commit -m "Initial commit"
docker run nginx

Why Useful: Makes the CLI modular, scalable, and easier to remember.


10. Testing and Benchmarking

Test harnesses and benchmark tools use arguments to adjust load, test cases, or parameters.

Example Use Case:

go test -bench=. -timeout=30s

Why Useful: Dynamic test configuration improves developer productivity.