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