Search code examples
goflagscommand-line-tool

Golang flag library: Unable to override Usage function that prints out command line usage


I am working on a simple command line tool and I found the default Usage message a bit lacking. I want to define my own and I think I am doing it right I am referring to this example.

I commented out most of the code I had written so the file containing the main function now looks like this:

package main

import (
    "flag"
    "fmt"
    "os"
)

func main() {
    // set the custom Usage function
    setupFlags(flag.CommandLine)
    // define flags...
    // then parse flags
    flag.Parse()
    // custom code that uses flag values...
}

func setupFlags(f *flag.FlagSet) {
    f.Usage = func() {
        fmt.Println("foo bar")
    }
}

It seems like this should work, but it doesn't. When running <binary> -h I get the default usage message and not my custom foo bar message that I defined in my custom function. I am using Go version 1.3.3 on OSX. I found this commit but it is for Go 1.4rc2.

What am I doing wrong?


Solution

  • Edit:

    Actually revisiting your code it works! What version of Go are you using? Maybe you need to rebuild your code.

    The decision of what Usage function to call is in the flag.go source file, line 708, unexported function usage() (this is from Go 1.4):

    func (f *FlagSet) usage() {
        if f.Usage == nil {
            if f == CommandLine {
                Usage()
            } else {
                defaultUsage(f)
            }
        } else {
            f.Usage()
        }
    }
    

    This tells if the FlagSet.Usage is not nil, it will be called. If it is not called for you, it's most likely you're using a Go version prior to 1.4 (which you confirmed in your comment).

    But since you're using the default flag.CommandLine flagset, you can simply write:

    // Note "flag.Usage" instead of "f.Usage"
    
    flag.Usage = func() {
        fmt.Println("foo bar")
    }