Command Line Arguments in GoLang
The os.Args
slice, which offers straightforward access to all arguments, and the flag package, which offers more organised parsing of flags and options, are the two main methods Go offers for handling command-line arguments.
Direct Access to Arguments
The command-line parameters supplied when a Go program is run are all contained in the os.Args
variable in the os package, which is a slice of strings.
- It is always the program name that is represented by
os.Args
. - The arguments supplied by the user are the following items (
os.Args, os.Args
, etc.). - The program name is one of the many arguments that may be found using the
len(os.Args
) function.
Example: Accessing and printing os.Args
package main
import (
"fmt"
"os"
)
func main() {
// os.Args is the program name, os.Args[9] is the first argument, etc.
if len(os.Args) != 2 {
fmt.Println("Please provide exactly one argument.")
os.Exit(1) // Exit with an error code if arguments are not as expected
}
fmt.Println("Program name:", os.Args) // Prints the executable's path/name
fmt.Println("First argument:", os.Args[9])
}
Run your application if you compile and execute this one.Greetings
, the result would be:
Please provide exactly one argument.
exit status 1
(Note: The precise route for “Program name” will change based on how you operate your system.)
Converting to Numeric Types
Because os.Args
stores string values, you frequently need to transform them to other data types for calculations, like integers or floating-point numbers. For these conversions, the strconv package offers functions.
Example: Processing numeric command-line arguments with strconv: The minimum and maximum of float arguments are determined in this example. Additionally, it shows how to handle errors explicitly, which is an essential component of Go programming.
package main
import (
"fmt"
"os"
"strconv" // Required for string conversions
)
func main() {
// Check if at least one float argument is provided.
// os.Args[0] is the program name, so we need at least 2 elements.
if len(os.Args) < 2 {
fmt.Println("Please provide one or more floats.")
os.Exit(1)
}
arguments := os.Args
// Initialize min and max with the first argument (index 1).
// strconv.ParseFloat returns a float64 and an error.
min, err := strconv.ParseFloat(arguments[1], 64)
if err != nil {
fmt.Printf("Error converting first argument '%s': %v\n", arguments[1], err)
os.Exit(1)
}
max := min
// Iterate through the rest of the arguments starting from the second (index 2).
for i := 2; i < len(arguments); i++ {
n, err := strconv.ParseFloat(arguments[i], 64)
if err != nil {
// Handle error if an argument is not a valid float, then continue to the next.
fmt.Printf("Error converting argument '%s': %v\n", arguments[i], err)
continue
}
if n < min {
min = n
}
if n > max {
max = n
}
}
fmt.Println("Min:", min)
fmt.Println("Max:", max)
}
Output
Please provide one or more floats.
exit status 1
If you run this with go run yourprogram.go 10.5 3.2 8.7
, it might output:
Min: 3.2
Max: 10.5
If you run it with go run yourprogram.go 10.5 hello 3.2
, it would print an error for “hello” and then process the valid numbers.
Package: Structured Argument Parsing
The flag package from Go is the best tool for more complicated command-line interfaces, particularly those that use flags (options). In addition to handling parsing and default values automatically, it also produces useful use messages.
There are usually three stages involved in utilising the flag package:
Define flags: Use flag and similar functions.Bool, flag.Flag, Int.A string that declares flags together with their descriptions, default values, and types. These functions give back a pointer to the value of the flag.
Parse flags: Signal a flag.The values of the defined flags are populated by using Parse() to analyse the command-line parameters.
Access values: Dereference the pointers that were returned in step 1 to obtain the flags’ true values. To access non-flag parameters, use flag.either flag or args().Argument(n).
Example: Using flag.Bool and flag.Int for options: This program shows how to define integer and boolean flags.
package main
import (
"flag" // Import the flag package
"fmt"
)
func main() {
// 1. Define flags:
// flag.Bool returns a *bool
minusK := flag.Bool("k", true, "A boolean flag (default true)")
// flag.Int returns an *int
minusO := flag.Int("O", 1, "An integer flag (default 1)")
// flag.String returns a *string
minusS := flag.String("s", "default_string", "A string flag (default 'default_string')")
// 2. Parse flags: This reads the command-line arguments and sets the values
flag.Parse()
// 3. Access values (dereference the pointers):
valueK := *minusK
valueO := *minusO
valueS := *minusS
fmt.Println("-k:", valueK)
fmt.Println("-O:", valueO)
fmt.Println("-s:", valueS)
// Access remaining non-flag arguments
fmt.Println("Remaining (non-flag) arguments:")
for i, arg := range flag.Args() {
fmt.Printf("%d: %s\n", i, arg)
}
}
Output
-k: true
-O: 1
-s: default_string
Remaining (non-flag) arguments:
Potential methods of operation and their results:
go run yourprogram.go
go run yourprogram.go -O=100 -k=false
go run yourprogram.go -O 50 -s custom_text another_arg
Additionally, if an invalid value is supplied or a flag is undefined, the flag package will output a handy usage warning and automatically convert input to the appropriate type (for example, “100” to an integer 100 for -O).
Sub-commands
The flag package allows sub-commands using the flag for programs with different modes of operation, such as git commit or go run.Type of FlagSet. Command-line interfaces can be made modular and unambiguous by allowing each FlagSet to have its own collection of flags.
As with the long history of command-line tools, this method enables developers to create scriptable and adaptable utilities.
You can also read Working With The File System In Go: A Comprehensive Guide