How to parse Command Line Arguments in Go
Beginners Guide to Parse flags (Command Line Arguments) in Go
Warming Up!
Go, (a.k.a. Golang), is an open-source programming language developed by Google.
It was designed to be efficient, concise, and easy to use while providing strong support for concurrent programming. Since Go has a lot of benefits like Simplicity, it is used by many developers currently.
Today we will be focusing on how to parse flags in Go.
Go comes with a built-in package for parsing flags, which is named “flag”(https://pkg.go.dev/flag).
We will be using the flag package for that tutorial.
Flag Package in Go
Go already provides a built-in package “flag
” that simplifies the process of parsing command line flags.
With this package we can easily define, parse or access the flags in the application. Let’s dive into examples!
How to define a Flag
We can define flags as String, Integer or Boolean types.
This declares an integer flag(-int) , stored in the pointer intFlag, with type *int and default value is 1111.
import "flag"
var intFlag = flag.Int("int", 1111, "help message for flag int")
It will be also the same for other types.
We declared 2 flags (-str and -bool) stored in strFlag and boolFlag with default values.
import "flag"
var(
strFlag = flag.String("str", "<default>", "help message for strFlag")
boolFlag= flag.Bool("bool", false, "help message for boolFlag")
)
If you like, you can bind the flag to a variable using the Var() functions.
var(
intFlag int
strFlag string
boolFlag bool
)
func main() {
flag.IntVar(&intFlag, "int", 1234, "help message")
flag.StringVar(&strFlag, "str", "default" , "help message")
flag.BoolVar(&boolFlag, "bool", false, "help message")
}
Command line flag syntax
The following forms can be used for passing the values:
-flag
--flag // double dashes are also permitted
-flag=x
-flag x // non-boolean flags only
Examples
Lets use the our flags in the examples.
package main
import (
"flag"
"fmt"
)
var(
intFlag int
strFlag string
boolFlag bool
)
func main() {
flag.IntVar(&intFlag, "int", 1234, "help message")
flag.StringVar(&strFlag, "str", "default" , "help message")
flag.BoolVar(&boolFlag, "bool", false, "help message")
flag.Parse()
fmt.Println("intFlag value is: ", intFlag)
fmt.Println("strFlag value is: ", strFlag)
fmt.Println("boolFlag value is: ", boolFlag)
}
In this example;
- The code starts by importing the necessary packages,
flag
andfmt
, which are part of Go's standard packages. - We declared three variables:
intFlag
,strFlag
, andboolFlag
. These variables will hold the values of the corresponding command-line flags. - We used the
flag.IntVar
,flag.StringVar
, andflag.BoolVar
functions to define the flags and associate them with the variables. - After defining the flags, the
flag.Parse()
function is called to parse the command-line arguments and set the values of the corresponding variables. Must be called after all flags are defined and before flags are accessed by the program. - Finally program prints the values of
intFlag
,strFlag
, andboolFlag
variables.
If we run this program without any flags, it will use the default values for variables.
go run .\main.go
//Output
intFlag value is: 1234
strFlag value is: default
boolFlag value is: false
We can send flags with arguments. Below we send flags and we can observe the output was changed.
go run .\main.go -int 12 -str hello! -bool=true
//Output
intFlag value is: 12
strFlag value is: hello!
boolFlag value is: true
Also you can execute a “-h, -help” flag for help messages for flags.
go run .\main.go -help
//Output
Usage of \go-build3444076518\b001\exe\main.exe:
-bool
help message
-int int
help message (default 1234)
-str string
help message (default "default")
If you don’t want to show “Usage of” part or customize the output you can check below:
flag.Usage = func() {
fmt.Fprintln(os.Stderr, "Flags:")
flag.PrintDefaults()
}
What is the difference between os.Args and flag package?
In Go, os.Args
and flag
package are used to access command-line arguments, but they serve different purposes.
os.Args
- “
os.Args
” is a variable that stores all command line arguments including program name itself. - It’s slice of strings
- The first element is (
os.Args[0]
) is the program name. - It will expand n times if you pass the arguments (
os.Args[n]
) os.Args
can be used when you want to access all the command line arguments as a string-slice.
flag package
- The
flag
package in Go provides a more sophisticated and structured approach to handle command-line arguments. - It allows you to define flags, specify default values, and provide help messages.
- It supports different types of flags such as boolean, string, integer, and more.
- The
flag
package handles the parsing and validation of the command-line arguments according to the defined flags. - It provides built-in functionality to automatically assign flag values to the associated variables.
- It supports flag aliases, shorthand flags, and flag grouping.
- The
flag
package also provides features like flag usage information, flag parsing errors, and custom flag parsing logic. - It simplifies the process of handling command-line arguments, especially when dealing with complex flag configurations.
We already know how to use flag package, let me give you some examples with os.Args
package main
import (
"fmt"
"os"
)
func main() {
fmt.Println("All arguments:", os.Args)
}
With this Go code we will print all arguments passed from command line:
go run .\main.go arg1 arg2 arg3
//Output
All arguments: [\main.exe arg1 arg2 arg3]
As you see we can see all the arguments we passed from command-line + program name itself.
We can parse these values as os.Args[n]
since this is a slice.
What if I need to use both of them?
Let’s imagine you need a program with parse command-line arguments as flags but you also need regular arguments without flags.
We can achieve this with flag.Args()
function.
flag.Args()
is a function provided by theflag
package.- It returns a slice of strings that contains the command-line arguments that have not been processed as flags by the
flag
package. - It excludes the program name and any flags that have been parsed using
flag.Parse()
. flag.Args()
is useful when you want to access the non-flag command-line arguments specifically.
Code Example:
package main
import (
"flag"
"fmt"
"os"
)
var(
intFlag int
strFlag string
boolFlag bool
)
func main() {
flag.IntVar(&intFlag, "int", 1234, "help message")
flag.StringVar(&strFlag, "str", "default" , "help message")
flag.BoolVar(&boolFlag, "bool", false, "help message")
flag.Parse()
fmt.Println("All arguments:", os.Args)
fmt.Println("Non-flag arguments:", flag.Args())
fmt.Println("-----")
fmt.Println("intFlag value is: ", intFlag)
fmt.Println("strFlag value is: ", strFlag)
fmt.Println("boolFlag value is: ", boolFlag)
}
With this code we can parse the flags and also prints the non-flag command-line arguments.
go run .\main.go -int 1 -str hello -bool=true arg1 arg2 arg3
//Output
All arguments: [\main.exe -int 1 -str hello -bool=true arg1 arg2 arg3]
Non-flag arguments: [arg1 arg2 arg3]
-----
intFlag value is: 1
strFlag value is: hello
boolFlag value is: true
As you see we can see everything we typed in command line as “All arguments”.
Non-Flag arguments we can see non-parsed arguments.
Important Note!
Flag parsing stops just before the first non-flag argument (“-” is a non-flag argument) or after the terminator “ — “.
It means you need to pass flags first.
If you pass the non-flag arguments first, it will not parse the flags and show them all as non-flag arguments.
go run .\main.go arg1 arg2 arg3 -int 1 -str hello -bool=true
//Output
All arguments: [\main.exe arg1 arg2 arg3 -int 1 -str hello -bool=true]
Non-flag arguments: [arg1 arg2 arg3 -int 1 -str hello -bool=true]
-----
intFlag value is: 1234
strFlag value is: default
boolFlag value is: false
In this example I passed the arg1, arg2, arg3 first.
Because of that it cannot parse the flags and show everything as non-flag arguments.
Summary
In summary, os.Args
is a basic mechanism to access command-line arguments as a slice of strings,
While the flag
package provides a higher-level abstraction for defining, parsing, and handling command-line flags with more control and functionality.
If you need advanced features like flag parsing, validation, and help messages, the flag
package is a recommended choice.
However, if you have simple command-line arguments without any specific flag requirements, os.Args
can be used for basic access to the arguments.