【发布时间】:2021-08-26 11:51:49
【问题描述】:
我正在实现一个带有多个子命令的小 CLI。我想支持全局标志,即适用于所有子命令以避免重复它们的标志。
例如,在下面的示例中,我尝试使用所有子命令所需的 -required 标志。
package main
import (
"flag"
"fmt"
"log"
"os"
)
var (
required = flag.String(
"required",
"",
"required for all commands",
)
fooCmd = flag.NewFlagSet("foo", flag.ExitOnError)
barCmd = flag.NewFlagSet("bar", flag.ExitOnError)
)
func main() {
flag.Parse()
if *required == "" {
fmt.Println("-required is required for all commands")
}
switch os.Args[1] {
case "foo":
fooCmd.Parse(os.Args[2:])
fmt.Println("foo")
case "bar":
barCmd.Parse(os.Args[2:])
fmt.Println("bar")
default:
log.Fatalf("[ERROR] unknown subcommand '%s', see help for more details.", os.Args[1])
}
}
我希望用法如下:
$ go run main.go foo -required helloworld
但如果我用上面的代码运行它,我会得到:
$ go run main.go foo -required hello
-required is required for all commands
flag provided but not defined: -required
Usage of foo:
exit status 2
看起来flag.Parse() 没有从 CLI 捕获 -required,然后 fooCmd 抱怨我给了它一个它无法识别的标志。
在 Golang 中使用带全局标志的子命令最简单的方法是什么?
【问题讨论】:
-
永远不要使用
go run main.go -
@Flimzy 不仅Eli说了什么,而且,没有解释?没有理由?这与手头的问题有关吗? :D
-
@EliBendersky:如果你认为我的评论是“火焰”,我很抱歉。建议很中肯。
-
@dbzuk:这与您的问题没有直接关系,这就是为什么它是评论而不是答案的原因。为什么不这样做的简短解释:因为 Go 中的编译单元是一个包,而不是一个文件,这通常意味着一个目录中的所有 .go 文件。它还忽略构建标签和其他极端情况。
go run main.go有时会起作用……直到不起作用。然后它令人困惑。所以最好不要养成这个习惯。
标签: go command-line-interface command-line-arguments