Can Go's `flag` package print usage?

Solution 1:

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

Solution 2:

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

Solution 3:

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

}