我有可以在多个组件中定义的标志。不可能知道一个组件是否已经定义了一个标志,例如如果两个组件Foo和Bar需要标志Zed,但是Foo和Bar必须定义标志Zed。在这种情况下,Go语言的标志会因为重新定义了一个错误标志而死机。
是否有任何方法可以选择初始化一个标志,只有当它还没有在其他地方初始化?或者检查是否已经设置了标志,如果已经设置,则查找标志值?
我看到的唯一方法是这样的:
var fooFlag *string
func init() {
if flag.Lookup("foo") == nil {
fooFlag = flag.String("foo", "", "some flag foo")
}
}
func initFlags() {
if fooFlag == nil && flag.Lookup("foo") != nil {
temp := (*flag.Lookup("foo")).Value.(flag.Getter).Get().(string)
fooFlag = &temp
}
}
func main() {
flag.Parse()
initFlags()
...
}
但这是令人难以置信的丑陋(也不确定这将如何工作)。有什么更好的办法吗?
2条答案
按热度按时间lmvvr0a81#
不幸的是,标准库没有更简单的方法,因为每个标志只能注册一次。我们将看到如何简化您的代码,以及如何避免这种模式。
Flag,FlagSet没有帮助
flag.FlagSet
的使用不是一个解决方案,它被设计为支持子命令(请参阅此问题的示例:Defining Independent FlagSets in GoLang)。为了说明为什么它没有帮助:让我们假设你有两个标志集(一个可能是
flag
包的细节)。第一标志集可以包含"foo"
和"bar"
标志,并且第二标志集可以包含"foo"
和"baz"
标志。如果用户提供了所有3个值,会发生什么?对第一个标志集的FlagSet.Parse()
的调用将报告错误:提供了标记但未定义:- 巴兹
类似地,第二个标志集的
FlagSet.Parse()
也会报告未定义的-bar
错误。简化代码
如果你想保持你的方法,请注意,你可以通过使用flag vars(
flag.StringVar()
)来简化你的代码,然后在initFlags()
中,你可以简单地得到一个string
值,并像这样赋值给你的flag变量:同样,如果你想像这样处理多个标志,那么你应该创建帮助函数来避免重复(现在不那么“丑陋”)的代码:
使用上面的helper,注册3个flag变量就像:
解决方案?
显而易见的解决方案是使用不同的名称。如果常用名称可能会冲突,您可以在它们前面加上前缀,例如。包名什么的但是你应该使用不同的、独特的、独特的名字。
想想吧如果你想使用相同的标志(相同的 * 名称 *),为什么你试图注册它两次,在2个不同的地方?
如果您确实想在多个地方使用同一个标志,那么就“外包”标志变量及其注册。例如,创建一个包,将照顾这一点,并从两个地方需要它,引用这个包。或者确保将flag变量的值分布到需要它的地方。
cnwbcb6i2#
我有一个函数,我在单元测试中运行了2次。当我运行我的测试,我得到'标志重新定义'错误。为了解决这个问题,我使用了flag.lookup函数,并检查了是否定义了标志。