Golang标志库:无法覆盖打印命令行用法的Usage函数。

huangapple go评论80阅读模式
英文:

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

问题

我正在开发一个简单的命令行工具,发现默认的使用消息有点不足。我想定义自己的使用消息,我认为我做得对,我参考了这个示例

我注释掉了我写的大部分代码,所以包含主函数的文件现在看起来像这样:

package main

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

func main() {
    // 设置自定义的使用函数
    setupFlags(flag.CommandLine)
    // 定义标志...
    // 然后解析标志
    flag.Parse()
    // 使用标志值的自定义代码...
}

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

看起来应该可以工作,但实际上并不行。当运行<binary> -h时,我得到的是默认的使用消息,而不是我在自定义函数中定义的foo bar消息。我在OSX上使用的是Go版本1.3.3。我找到了这个提交,但它是针对Go 1.4rc2的。

我做错了什么?

英文:

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 (
    &quot;flag&quot;
    &quot;fmt&quot;
    &quot;os&quot;
)

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(&quot;foo bar&quot;)
    }
}

It seems like this should work, but it doesn't. When running &lt;binary&gt; -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?

答案1

得分: 8

实际上,重新审视你的代码,它是可以工作的!你使用的是哪个版本的Go语言?也许你需要重新构建你的代码。

决定调用哪个Usage函数的代码位于flag.go源文件的第708行,这是一个未导出的函数usage()(这是从Go 1.4开始的):

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

这段代码的意思是,如果FlagSet.Usage不是nil,就会调用它。如果它对你没有起作用,很可能是因为你使用的是早于1.4版本的Go语言(正如你在评论中确认的那样)。

但是,由于你使用的是默认的flag.CommandLine标志集,你可以简单地写成:

// 注意这里是"flag.Usage"而不是"f.Usage"
flag.Usage = func() {
    fmt.Println("foo bar")
}
英文:

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 &quot;flag.Usage&quot; instead of &quot;f.Usage&quot;

flag.Usage = func() {
    fmt.Println(&quot;foo bar&quot;)
}

huangapple
  • 本文由 发表于 2015年1月22日 23:03:35
  • 转载请务必保留本文链接:https://go.coder-hub.com/28091963.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定