Background#
flag.Bool and flag.BoolVar exhibit strange behavior
When the default value is set to true,
// flag.BoolVar
func main() {
var getBool bool
flag.BoolVar(&getBool, "get", true, "get a boolean")
flag.Parse()
fmt.Println(getBool)
}
# Result
go run main.go -get false
true
// flag.Bool
func main() {
var getBool *bool
getBool = flag.Bool("get", true, "get a boolean")
flag.Parse()
fmt.Println(*getBool)
}
# Result
go run main.go -get false
true
However, when the default value is set to false and the command line argument is set to true, the code behaves normally (only one case is shown due to consistent results)
func main() {
var getBool *bool
getBool = flag.Bool("get", false, "get a boolean")
flag.Parse()
fmt.Println(*getBool)
}
# Result
go run main.go -get true
true
Why#
Let's take a look at the code comments
// src/flag/flag.go
// A Flag represents the state of a flag.
type Flag struct {
Name string // name as it appears on command line
Usage string // help message
Value Value // value as set
DefValue string // default value (as text); for usage message
}
// Value is the interface to the dynamic value stored in a flag.
// (The default value is represented as a string.)
//
// If a Value has an IsBoolFlag() bool method returning true,
// the command-line parser makes -name equivalent to -name=true
// rather than using the next command-line argument.
//
// Set is called once, in command line order, for each flag present.
// The flag package may call the [String] method with a zero-valued receiver,
// such as a nil pointer.
type Value interface {
String() string
Set(string) error
}
The bool flag -name will be parsed by the parser as -name=true instead of parsing the next argument
# For example, false after -b will not be parsed
# The following command is equivalent to go run main.go -b=true
go run main.go -b false
How to Solve#
Use -name=false instead of -name false
# Result
go run main.go -get=true -come=false -num 1
true
false
1