Golang冲突的命令行标志

时间:2012-12-05 04:41:40

标签: go

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

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

注意:不确定这是否相关,但它只发生在我的某些软件包而不是其他软件包中。我假设它只是基于订单决定导入包,但我想如果这是相关的话我会提到它。

还有其他人遇到过这个问题吗?是否有一种简单的方法可以让所有标志组合而不会被破坏,或者使gocheck标志优先于我的自定义标志?

1 个答案:

答案 0 :(得分:14)

如果多个包调用flag.Parse而不关心定义其他标志的其他包那么你就遇到麻烦了(正如你已经体验过的那样)。 “flag”包的状态是一个全局状态,因此它或多或少相同,就好像不同的包将竞争在init期间将全局变量的值设置为不同的值。显然,这可能不会很好。

防止这种情况的简单方法:flag.Parse只应调用一次(在第一次近似中)。这就是为什么它通常只在包“main”中看到。如果您的非主程序包调用flag.Parse,那么它通常会与程序包“main”中调用的任何flag.Parse冲突。请注意go test合成package main以测试包,并且从合成的“主”包中调用flag.Parse

另一方面,它更“安全”(但无论如何都可能发生冲突)只在非主包中定义标志,并且依赖flag.Parse将在包“main”中调用。在非主程序包中,可以使用flag.Parsed()验证是否已调用flag.Parse

上面的简化。有关其他选项,请检查包标志documentation。在某些情况下可以通过使用flag.Flagset获得更多“权力”,即在包中使用 local 状态作为标记选项。

但是,我个人不希望以任何方式在包“main”之外使用包“flag”,而是通过其API设置任何可配置包行为。但是,确实存在例外情况,例如在* _test文件或其他特殊情况下。