Golang命令行参数冲突

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

Golang conflicting command line flags

问题

我在使用gocheck运行测试时遇到了问题。我需要传递一个标志来指定要运行的测试,例如go test -gocheck.f ApiSuite.TestSomeFunction

我的测试文件导入了一个设置包,在其中有一个init()函数,它指定了自己的标志并调用了flag.parseFlags()。我遇到的问题是,这似乎覆盖了gocheck的标志,所以我会收到一个错误,指出未识别标志-gocheck.f。

注意:不确定这是否相关,但这只发生在我的一些包中,而不是其他包中。我猜这只是基于go决定导入包的顺序,但我想提一下,以防这是相关的。

有其他人遇到过这个问题吗?有没有简单的方法可以让所有标志合并而不被覆盖,或者让gocheck的标志优先于我的自定义标志?

英文:

I'm having trouble running tests using gocheck. I need to pass it a flag to specify which test to run, e.g. go test -gocheck.f ApiSuite.TestSomeFunction.

My test file imports a settings package, in which there's an init() function that specifies its own flags and calls flag.parseFlags(). The problem I'm having is that this seems to be overriding the gocheck flags, so I get an error that the flag -gocheck.f is not recognized.

Note: Not sure if this is relevant, but it only happens in some of my packages and not others. I assume it's just based on the order go decides to import the packages in, but I thought I'd mention it in case this is relevant.

Has anyone else run into this problem? Is there a simple way to just have all the flags combine without getting clobbered, or to make the gocheck flags take precedence over my custom flags?

答案1

得分: 14

如果有多个包在没有考虑其他包定义其他标志的情况下调用flag.Parse,那么你就会遇到麻烦(正如你已经经历过的)。"flag"包的状态是全局状态,所以这与不同的包在init期间竞争将一个全局变量的值设置为不同的值几乎是一样的。显然,这可能不会有好的结果。

防止这种情况的简单方法是:只调用一次flag.Parse(在第一次近似中)。这就是为什么它通常只在包"main"中出现。如果你的非主要包调用了flag.Parse,那么它通常会与包"main"中调用的任何flag.Parse冲突。请注意,go test会合成一个"main"包来测试一个包,并且flag.Parse会从该合成的"main"包中调用。

另一方面,只在非主要包中定义标志,并依赖于在包"main"中调用flag.Parse可能更"安全"(但冲突仍然可能发生)。在非主要包中,可以使用flag.Parsed()来验证是否已调用flag.Parse。

上面所写的是简化的。有关其他选项,请查看flag包的文档。在某些情况下,可以通过使用FlagSet(例如,使用包内的局部状态)来获得更多的"权力"。

然而,我个人更喜欢在包"main"之外的地方不使用flag包,而是通过其API来设置任何可配置的包行为。当然,也存在例外情况,例如*_test文件或其他特殊情况。

英文:

If more than one package calls flag.Parse without any concerns about other packages defining other flags then you're in trouble (as you've experienced already). The state of the "flag" package is a global state, so it's more or less the same as if different packages would be competing to set a value of a global variable during init to different values. That may not end well, obviously.

The easy way to prevent this: flag.Parse should be called only once (in the first approximation). That's why it is normally seen in package "main" only. If your non-main package calls flag.Parse then it typically will conflict with any flag.Parse called in package "main". Note that go test synthesizes a package main in order to test a package and flag.Parse is called from that synthesized "main" package.

On the other hand, it is more "safe" (but conflicts are possible anyway) to only define flags in a non-main package and rely on flag.Parse would be called in package "main". In the non-main package, one can then verify that flag.Parse has been invoked by using flag.Parsed().

Written above is simplified. For additional options check the package flag documentation. More "power" could be acquired in some scenarios by, for example, using flag.Flagset, i.e. by using local state for flag options within a package.

However, I personally prefer not to use package "flag" outside of package "main" in any way and rather to set up any configurable package behavior through its API. Exceptions do exist, though, e.g. in *_test files or other special cases.

huangapple
  • 本文由 发表于 2012年12月5日 12:41:39
  • 转载请务必保留本文链接:https://go.coder-hub.com/13716444.html
匿名

发表评论

匿名网友

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

确定