Home > Blockchain >  Is a bug: flag.Parse() could not get values after bool arg?
Is a bug: flag.Parse() could not get values after bool arg?

Time:09-30

Why could not get the values that following bool type arg in the command line?
Here's my test code:

import (
    "flag"
    "fmt"
)

var stringVal string
var intVal int
var boolValue bool

func init() {
    flag.StringVar(&stringVal, "s", "", "string value")
    flag.BoolVar(&boolValue, "b", false, "bool value")
    flag.IntVar(&intVal, "i", -1, "int value")
}

func main() {
    flag.Parse()

    fmt.Println("stringVal:", stringVal, ", boolValue:", boolValue, ", intVal:", intVal)
}

Run it as:

  • go run flag.go -s test -b true -i 10
    Got: stringVal: test , boolValue: true , intVal: -1
  • go run flag.go -s test -b false -i 10
    Got: stringVal: test , boolValue: true , intVal: -1
  • go run flag.go -b false -s test -i 10
    Got: stringVal: , boolValue: true , intVal: -1
  • go run flag.go -s test -i 10 -b false
    Got: stringVal: test , boolValue: true , intVal: 10

Go version: 1.16

CodePudding user response:

Boolean flags are set based on the presence or absence of the flag. They typically default to false, and the presence of the flag is used to modify the default behavior.

For example...

  • to display the long listing of a directory with ls, you use ls -l, not ls -l true
  • to make rm safer by having it interactively prompt for deletes, you use rm -i, not rm -i true
  • to display human-readable output with df, you use df -h, not df -h true

The true and false you're placing after the -b are being provided to your program as arguments, not as flags, and their presence interrupts further processing of flags.

Add the following to the end of your main function:

fmt.Println("Remaining args", flag.Args())

Given an invocation such as go run flag.go -b false -s test -i 10, you'll see that flag processing stopped at false, and that the remaining arguments are passed to your program as non-flag arguments:

$ go run flag.go -b false -s test -i 10
stringVal:  , boolValue: true , intVal: -1
Remaining args [false -s test -i 10]

As an aside, the general philosophy behind "boolean" flags is that you give your program some default behavior, and provide two flags: One which modifies that default, and an opposite flag that negates the modification, restoring the default. When processing flags, the last flag will win.

For example, rm provides -i to make the command interactive, and -f to negate the -i flag.

This allows you to set alias rm="rm -i" in your shell, meaning all invocations of rm will have the -i flag applied for safety, prompting you before removing files. However, if you want to run a non-interactive rm, you can still type rm -f, which expands to be rm -i -f, and the last flag (-f) wins. Otherwise, you'd have destroy the alias, run rm and then restore the alias every time you wanted a non-interactive invocation.

CodePudding user response:

A boolean flag tests the existence of the flag, not the value of it. If you want to set a value, use:

go run flag.go -s test -b=false -i 10
  •  Tags:  
  • go
  • Related