Go by Example

Command-Line Arguments

os.Args provides raw access to command-line arguments as a string slice, with os.Args[0] holding the binary name and os.Args[1:] holding the user-supplied arguments.

os.Args is a []string containing the raw command-line arguments. os.Args[0] is the path to the running binary; os.Args[1:] contains everything the user typed after the binary name.

Access os.Args directly for simple tools that take positional arguments. The slice is always non-nil - when no arguments are given, os.Args has length 1 (just the binary name).

package main
 
import (
    "fmt"
    "os"
)
 
func main() {
    args := os.Args
 
    fmt.Println("binary:", args[0])
    fmt.Println("args:  ", args[1:])
    fmt.Println("count: ", len(args)-1)
}

Check argument count before indexing to avoid an index-out-of-range panic. Access individual arguments by index after validating length.

package main
 
import (
    "fmt"
    "os"
)
 
func main() {
    if len(os.Args) < 2 {
        fmt.Fprintln(os.Stderr, "usage: greet <name>")
        os.Exit(1)
    }
 
    name := os.Args[1]
    fmt.Printf("Hello, %s!\n", name)
}

Iterate over all provided arguments with a range loop over os.Args[1:].

package main
 
import (
    "fmt"
    "os"
    "strings"
)
 
func main() {
    args := os.Args[1:]
 
    if len(args) == 0 {
        fmt.Println("no arguments provided")
        return
    }
 
    fmt.Println("joined:", strings.Join(args, ", "))
 
    for i, arg := range args {
        fmt.Printf("  [%d] %s\n", i, arg)
    }
}

In production

os.Args is appropriate for positional arguments in simple, single-purpose tools. For anything with optional flags (--verbose, --output=file), use the flag package - it generates consistent help text and handles the -- convention automatically. For tools with subcommands (git commit, docker run), use flag.FlagSet per subcommand or a library like cobra. Parsing os.Args by hand for complex CLIs produces fragile code that fails on edge cases (arguments with spaces, -- end-of-flags, - as stdin indicator) that users expect to work. Never use os.Args[0] to infer the install location of the binary at runtime - use os.Executable() instead, which resolves symlinks.

Enjoyed this? Get more essays on software craft delivered to your inbox.

Subscribe free