Go Command Line
Go makes it easy to build command-line tools. You can either access arguments directly or use the flag package for a more structured approach.
1. Basic Arguments
The os.Args slice contains everything the user typed to start the program.
| package main
import (
"fmt"
"os"
)
func main() {
// os.Args[0] is the path to the program itself
// os.Args[1:] are the actual arguments
argsWithProg := os.Args
argsWithoutProg := os.Args[1:]
fmt.Println(argsWithProg)
fmt.Println(argsWithoutProg)
}
|
2. Command-Line Flags
Flags are structured options (like -v or --port=8080). Go's flag package handles parsing.
| package main
import (
"flag"
"fmt"
)
func main() {
// 1. Define flags (name, default value, help text)
wordPtr := flag.String("word", "foo", "a string")
numbPtr := flag.Int("numb", 42, "an int")
forkPtr := flag.Bool("fork", false, "a bool")
// 2. You must call Parse()
flag.Parse()
// 3. Use pointers to access values
fmt.Println("word:", *wordPtr)
fmt.Println("numb:", *numbPtr)
fmt.Println("fork:", *forkPtr)
// Access non-flag arguments
fmt.Println("tail:", flag.Args())
}
|
3. Sub-Commands
For complex tools (like go run or git commit), you can use flag.NewFlagSet.
| fooCmd := flag.NewFlagSet("foo", flag.ExitOnError)
barCmd := flag.NewFlagSet("bar", flag.ExitOnError)
if len(os.Args) < 2 {
fmt.Println("expected 'foo' or 'bar' subcommands")
os.Exit(1)
}
switch os.Args[1] {
case "foo":
fooCmd.Parse(os.Args[2:])
case "bar":
barCmd.Parse(os.Args[2:])
}
|
Why use Flags?
- Standardization: Users expect
-h or --help to show instructions. Go's flag package generates this automatically.
- Type Safety: It automatically converts strings ("8080") into the correct Go type (
int).
- Third-Party Libraries: For larger apps, most Go developers use Cobra—the same library that powers Docker and Kubernetes.