此示例 Cobra 应用程序,https://github.com/kurtpeek/myCobraApp , 包含一个使用 Cobra 生成器搭建的 Cobra 应用程序,其中包含以下命令:
cobra add serve
cobra add config
目录结构为
.
├── LICENSE
├── cmd
│ ├── config.go
│ ├── root.go
│ └── serve.go
├── go.mod
├── go.sum
└── main.go
在
config.go
, 字符串变量 deviceUUID
已定义并绑定(bind)到该命令的标志,默认值为 "configDeviceUUID"
:var deviceUUID string
func init() {
rootCmd.AddCommand(configCmd)
// Cobra supports local flags which will only run when this command
// is called directly, e.g.:
configCmd.Flags().StringVar(&deviceUUID, "deviceUUID", "configDeviceUUID", "Device UUID")
fmt.Println("deviceUUID after config init:", deviceUUID)
}
同样,在
serve.go
deviceUUID
变量绑定(bind)到本地标志:func init() {
rootCmd.AddCommand(serveCmd)
serveCmd.Flags().StringVar(&deviceUUID, "deviceUUID", "serveDeviceUUID", "Device UUID")
fmt.Println("deviceUUID after serve init:", deviceUUID)
}
问题是如果我运行
config
命令未指定 deviceUUID
命令行中的标志,它从 serve
中获取默认值命令:> go run main.go config
deviceUUID after config init: configDeviceUUID
deviceUUID after serve init: serveDeviceUUID
deviceUUID: serveDeviceUUID
config called
似乎正在发生的是
init()
每个文件中的函数按字母顺序运行,最后运行的函数设置标志的默认值。我怎样才能避免这种行为?我想要
config.go
中设置的默认值始终适用于 config
命令。 (当然,我可以声明单独的变量,如 configDeviceUUID
和 serveDeviceUUID
,但这对我来说似乎有点困惑)。
最佳答案
我不知道你为什么会认为那是乱七八糟的。你有一个变量,你把它设置在几个 init
功能,所以最后一个设置是保持设置的那个:你对正在发生的事情的解释是正确的。显然,这实际上是两个不同的变量,只是实际上最多使用其中一个。
(假设还有其他命令可以做其他事情,也许这些全局变量都不会被使用。如果 Go 是一种自然更动态的语言,其中一切都在运行时决定,或者如果您使用的是更动态的运行时设置,你可能还没有创建它们。但这不是 Go:Go 充满了静态类型和静态变量,在链接时创建。)
但是,如果您确实只想使用一个全局变量,显而易见的解决方案是选择一些标记值来表示未设置,并将其设为 Cobra 设置的默认值。然后,如果变量在运行命令时保持“未设置”值,您就知道用户没有提供值。
如果空字符串适合作为这样的哨兵——通常就是这种情况——这很容易。您的每个命令都有几行:
if deviceUUID == "" {
deviceUUID = defaultDeviceUUID
}
你就完成了。
如果 cobra 代码在您这样做时将默认初始化器值保存在某个私有(private)位置,这可能会很好,或者至少对您来说更方便:
configCmd.Flags().StringVar(&deviceUUID, "deviceUUID", "configDeviceUUID", "Device UUID")
然后当顶级命令决定
config
时,将那些私有(private)的、保存的默认值复制到(单个)全局变量中。将使用子命令,而不是将其保存在私有(private)的某个地方,然后将其复制到当时的(单个)全局变量中 configCmd.Flags().StringVar()
函数被调用,但这不是它的实际工作方式。所以:configCmd.Flags().StringVar(&deviceUUID, "deviceUUID", "", "Device UUID")
加上上面的空字符串测试可能就足够了。请注意,每个
init
仍然每次都覆盖(单个、共享和可能从未使用过的)全局变量,但所有变量都将其从初始空字符串值设置为新的空字符串值,保持不变。
关于go - 在 Cobra 命令行工具中,如何为不同的标志使用相同的变量?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60443941/