简体   繁体   中英

Can Go's `flag` package print usage?

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

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")
}

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
    })
}

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.

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")

}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM