问题 Golang冲突的命令行标志


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

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

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

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


2700
2017-12-05 04:41


起源



答案:


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

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

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

写在上面  简化。有关其他选项,请检查包标志 文件。在某些情况下可以通过例如使用获得更多“功率” flag.Flagset,即通过使用 本地 包中的标志选项的状态。

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


14
2017-12-05 06:58



谢谢。我实际上通过匿名导入gocheck到我的设置文件中,通过试验和错误修复了代码,现在所有的标记一起工作。在阅读完答案并查看gocheck源代码后,我明白为什么会这样 - gocheck从不调用flag.Parse(),所以我必须确保在调用settings.init()方法之前导入gocheck并且所有标志都将一起工作。虽然只有解析主要标志的好建议,但我会记住未来。 - danny


答案:


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

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

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

写在上面  简化。有关其他选项,请检查包标志 文件。在某些情况下可以通过例如使用获得更多“功率” flag.Flagset,即通过使用 本地 包中的标志选项的状态。

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


14
2017-12-05 06:58



谢谢。我实际上通过匿名导入gocheck到我的设置文件中,通过试验和错误修复了代码,现在所有的标记一起工作。在阅读完答案并查看gocheck源代码后,我明白为什么会这样 - gocheck从不调用flag.Parse(),所以我必须确保在调用settings.init()方法之前导入gocheck并且所有标志都将一起工作。虽然只有解析主要标志的好建议,但我会记住未来。 - danny