The Golang flag package is the standard way to handle command-line arguments in Go applications. It allows developers to define flags, set default values, and control program behavior dynamically based on user input, making it essential for building CLI tools and automation scripts.
In this guide, you will learn everything from basic flag usage to advanced techniques like handling multiple values, required flags, and subcommands. With practical examples and real-world scenarios, this tutorial will help you master Go command-line flags and build production-ready CLI applications.
Golang Flag Quick Cheat Sheet (Most Used Patterns)
| Command / Code Example | Description |
|---|---|
name := flag.String("name", "guest", "username") | Define a string flag with default value |
port := flag.Int("port", 8080, "port number") | Define an integer flag |
debug := flag.Bool("debug", false, "enable debug") | Define a boolean flag |
flag.Parse() | Parse command-line inputs |
fmt.Println(*name) | Dereference pointer to get value |
flag.StringVar(&name, "name", "guest", "username") | Bind flag to existing variable |
flag.Args() | Retrieve non-flag arguments |
flag.Arg(0) | Get positional argument |
flag.NArg() | Count non-flag arguments |
flag.Usage() | Print usage message |
flag.Usage = func() {} | Customize help output |
if name == "" { os.Exit(1) } | Validate required flags manually |
flag.Var(&list, "item", "add items") | Custom flag for multiple inputs |
flag.NewFlagSet("cmd", flag.ExitOnError) | Create CLI subcommands |
go run main.go -name=John | Pass flags via CLI |
-debug | Sets boolean flag to true |
-port=8080 -debug=true | Use multiple flags together |
Basic Golang Flag Usage
Simple string, int and bool flag examples
Understand how to define basic flag types like string, integer, and boolean in Go CLI applications.
package main
import (
"flag"
"fmt"
)
func main() {
name := flag.String("name", "guest", "username")
port := flag.Int("port", 8080, "port number")
debug := flag.Bool("debug", false, "enable debug")
flag.Parse()
fmt.Println("Name:", *name)
fmt.Println("Port:", *port)
fmt.Println("Debug:", *debug)
}Run Go program with flags (go run flags)
Learn how to pass command-line flags while running Go programs using go run.
go run main.go -name=John -port=9090 -debug=trueDefault values and usage messages
Understand how default values work and how to display usage information for CLI users.
package main
import (
"flag"
)
func main() {
name := flag.String("name", "guest", "username")
flag.Parse()
flag.Usage()
}Multiple Flags and Real CLI Examples
Use multiple flags together in a program
Combine multiple flags to control different aspects of application behavior.
package main
import (
"flag"
"fmt"
)
func main() {
host := flag.String("host", "localhost", "server host")
port := flag.Int("port", 8080, "server port")
debug := flag.Bool("debug", false, "enable debug")
flag.Parse()
fmt.Printf("Connecting to %s:%d (debug=%v)\n", *host, *port, *debug)
}Build a real CLI tool with flags
Example of a simple CLI tool using flags for configuration.
package main
import (
"flag"
"fmt"
)
func main() {
filename := flag.String("file", "data.txt", "input file")
mode := flag.String("mode", "read", "operation mode")
flag.Parse()
fmt.Println("File:", *filename)
fmt.Println("Mode:", *mode)
}Combine flags with positional arguments
Use flags along with positional arguments for flexible CLI input handling.
package main
import (
"flag"
"fmt"
)
func main() {
user := flag.String("user", "guest", "username")
flag.Parse()
args := flag.Args()
fmt.Println("User:", *user)
fmt.Println("Arguments:", args)
}Handling Required Flags in Golang
How to make flags mandatory (manual validation)
Golang does not support required flags directly, so validation must be done manually.
package main
import (
"flag"
"fmt"
"os"
)
func main() {
name := flag.String("name", "", "username (required)")
flag.Parse()
if *name == "" {
fmt.Println("Error: -name flag is required")
os.Exit(1)
}
fmt.Println("Name:", *name)
}Show custom error if flag is missing
Display user-friendly error messages and usage instructions when required flags are not provided.
package main
import (
"flag"
"fmt"
"os"
)
func main() {
name := flag.String("name", "", "username")
flag.Usage = func() {
fmt.Println("Usage:")
fmt.Println(" -name string (required)")
}
flag.Parse()
if *name == "" {
flag.Usage()
os.Exit(1)
}
fmt.Println("Name:", *name)
}Best practice for required flags
Combine validation and clear usage messages to improve CLI usability and avoid runtime errors.
if *name == "" {
fmt.Println("Missing required flag: -name")
flag.Usage()
os.Exit(1)
}Working with Multiple Values (Array Flags)
Accept multiple values using custom flag types
Use custom flag types to accept multiple values by implementing the flag.Value interface.
package main
import (
"flag"
"fmt"
)
type StringSlice []string
func (s *StringSlice) String() string {
return fmt.Sprint(*s)
}
func (s *StringSlice) Set(value string) error {
*s = append(*s, value)
return nil
}
func main() {
var items StringSlice
flag.Var(&items, "item", "add multiple items")
flag.Parse()
fmt.Println("Items:", items)
}Run:
go run main.go -item apple -item banana -item mangogolang flag array example
Example of collecting multiple inputs into an array-like structure.
// Output:
Items: [apple banana mango]Repeat flags vs comma-separated values
Understand two common approaches for passing multiple values via flags.
# Repeat flag (recommended)
go run main.go -item apple -item banana
# Comma-separated (manual parsing required)
go run main.go -item apple,bananaGolang Flag Subcommands (Advanced CLI Design)
Create subcommands using flag.NewFlagSet
Use flag.NewFlagSet to define independent flag sets for each subcommand.
package main
import (
"flag"
"fmt"
"os"
)
func main() {
addCmd := flag.NewFlagSet("add", flag.ExitOnError)
value := addCmd.Int("value", 0, "value to add")
if len(os.Args) < 2 {
fmt.Println("expected 'add' subcommand")
os.Exit(1)
}
switch os.Args[1] {
case "add":
addCmd.Parse(os.Args[2:])
fmt.Println("Added:", *value)
default:
fmt.Println("unknown command")
}
}Example: git-like CLI using subcommands
Demonstrates how modern CLI tools structure commands and flags.
go run main.go add -value=10Parsing and Validating Flags
flag.Parse explained with examples
flag.Parse processes command-line inputs and assigns values to defined flags.
flag.Parse()Validate flag inputs (range, format)
Validate inputs such as port range or string format after parsing.
if *port < 1 || *port > 65535 {
fmt.Println("Invalid port number")
os.Exit(1)
}Handle invalid or unexpected inputs
Handle errors gracefully to improve CLI user experience.
if *name == "" {
fmt.Println("Name cannot be empty")
os.Exit(1)
}Boolean and String Flags Deep Dive
golang flag bool behavior (true/false nuances)
Boolean flags default to false and become true when specified without a value.
go run main.go -debugEquivalent to:
go run main.go -debug=trueflag.String vs StringVar difference
Understand the difference between pointer-based and variable-based flag definitions.
// Pointer-based
name := flag.String("name", "guest", "username")
// Variable-based
var username string
flag.StringVar(&username, "name", "guest", "username")Common mistakes with string flags
Avoid common errors like forgetting to parse flags or not dereferencing pointer values.
flag.Parse()
fmt.Println(*name) // correct
// fmt.Println(name) // incorrect (prints pointer)Using Flags with Environment Variables
Override flags using environment variables
Override flag values using environment variables to allow dynamic configuration without modifying code.
package main
import (
"flag"
"fmt"
"os"
)
func main() {
env := flag.String("env", "dev", "environment")
flag.Parse()
if val := os.Getenv("APP_ENV"); val != "" {
*env = val
}
fmt.Println("Environment:", *env)
}Run:
APP_ENV=prod go run main.goConfig fallback pattern (env → flag → default)
Implement a layered configuration approach where environment variables override flags, and flags override default values.
env := flag.String("env", "dev", "environment")
flag.Parse()
if *env == "dev" {
if val := os.Getenv("APP_ENV"); val != "" {
*env = val
}
}Real-world DevOps use case
Use flags and environment variables together in automation scripts, containers, and CI/CD pipelines.
APP_ENV=staging go run main.go -env=devOutput:
Environment: stagingError Handling and Custom Usage Output
Customize flag usage message
Override the default usage output to provide clearer instructions to users.
flag.Usage = func() {
fmt.Println("Usage of application:")
fmt.Println(" -name string (required)")
}Control error handling behavior
Use different error handling modes like ExitOnError or ContinueOnError for better control.
cmd := flag.NewFlagSet("app", flag.ExitOnError)Improve CLI UX with help messages
Provide meaningful help messages to guide users and reduce errors.
flag.Usage = func() {
fmt.Println("Example:")
fmt.Println(" go run main.go -name=John")
}Summary
This guide covered everything you need to know about the Golang flag package, from basic usage to advanced CLI patterns like multiple values, subcommands, environment variable integration, and error handling. By applying these techniques, you can build flexible, user-friendly, and production-ready command-line applications in Go.
Official Documentation
For more details and advanced usage, refer to the official Golang documentation:





![GO Bytes to String Conversion Best Practices [5 Methods]](/go-bytes-to-string/golang-byte-to-string_hu_e997372962029da.webp)




