Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can Go's `flag` package print usage?

Tags:

go

Is it possible for me to customize Go's flag package so that it prints a custom usage string? I have an application with current output

Usage of ./mysqlcsvdump:
  -compress-file=false: whether compress connection or not
  -hostname="": database host
  -outdir="": where output will be stored
  -password="": database password
  -port=3306: database port
  -single-transaction=true: whether to wrap everything in a transaction or not.
  -skip-header=false: whether column header should be included or not
  -user="root": database user

and would rather have something like

Usage: ./mysqlcsvdump [options] [table1 table2 ... tableN]

Parameters:
  -compress-file=false: whether compress connection or not
  -hostname="": database host
  -outdir="": where output will be stored
  -password="": database password
  -port=3306: database port
  -single-transaction=true: whether to wrap everything in a transaction or not.
  -skip-header=false: whether column header should be included or not
  -user="root": database user
like image 437
Ztyx Avatar asked May 18 '14 19:05

Ztyx


People also ask

How do you use the flag package in go?

Using the flag package involves three steps: First, define variables to capture flag values, then define the flags your Go application will use, and finally, parse the flags provided to the application upon execution.

How do you use the flag command?

Command-line flags Bool() , flag.Int() , etc. After you've defined your flags, you need to call flag. Parse() . This call will execute command-line parsing and will let you use the flags.


4 Answers

Yes, you can do that by modifying flag.Usage:

var Usage = func() {
        fmt.Fprintf(os.Stderr, "Usage of %s:\n", os.Args[0])

        flag.PrintDefaults()
}

Usage prints to standard error a usage message documenting all defined command-line flags. The function is a variable that may be changed to point to a custom function.

Example use from outside of flag:

flag.Usage = func() {
    fmt.Fprintf(os.Stderr, "This is not helpful.\n")
}
like image 187
nemo Avatar answered Oct 22 '22 16:10

nemo


If you want full customisation over your usage, you need to reimplement the flag.Usage() function by using flag.VisitAll() to iterate through all the parsed flags. For example:

flag.Usage = func() {
    fmt.Fprintf(os.Stderr, "Custom help %s:\n", os.Args[0])
    
    flag.VisitAll(func(f *flag.Flag) {
        fmt.Fprintf(os.Stderr, "    %v\n", f.Usage) // f.Name, f.Value
    })
}
like image 24
Ivan Avatar answered Oct 22 '22 16:10

Ivan


In Feb 2018, Go 1.10 updated the default destination of flag output:

The default Usage function now prints its first line of output to CommandLine.Output() instead of assuming os.Stderr, so that the usage message is properly redirected for clients using CommandLine.SetOutput.

(see also flag.go)

So if you want to customize your flag usage, don't assume os.Stderr, instead use something like:

flag.Usage = func() {
    w := flag.CommandLine.Output() // may be os.Stderr - but not necessarily

    fmt.Fprintf(w, "Usage of %s: ...custom preamble... \n", os.Args[0])

    flag.PrintDefaults()

    fmt.Fprintf(w, "...custom postamble ... \n")

}
like image 2
colm.anseo Avatar answered Oct 22 '22 15:10

colm.anseo


And finally, in Go 1.16.4 we have:

// Output returns the destination for usage and error messages. os.Stderr is returned if
// output was not set or was set to nil.
func (f *FlagSet) Output() io.Writer {
    if f.output == nil {
        return os.Stderr
    }
    return f.output
}

So, by default it uses os.Stderr, otherwise what was set to the output.

like image 1
Sergey Sarbash Avatar answered Oct 22 '22 15:10

Sergey Sarbash