dbz*_*zuk 13 command-line-interface go command-line-arguments
我正在实现一个带有多个子命令的小型 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])
}
}
Run Code Online (Sandbox Code Playgroud)
我希望用法如下:
$ go run main.go foo -required helloworld
Run Code Online (Sandbox Code Playgroud)
但如果我用上面的代码运行它,我会得到:
$ 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
Run Code Online (Sandbox Code Playgroud)
它看起来像是flag.Parse()没有-required从 CLI 捕获,然后它fooCmd抱怨我给了它一个它无法识别的标志。
在 Golang 中使用带有全局标志的子命令的最简单方法是什么?
icz*_*cza 17
如果您打算实现子命令,则不应调用flag.Parse().
相反,决定使用哪个子命令(就像您对 所做的那样os.Args[1]),并仅调用其FlagSet.Parse()方法。
是的,为此,所有标志集都应包含通用标志。但将它们注册一次(在一个地方)很容易。创建包级别变量:
var (
required string
fooCmd = flag.NewFlagSet("foo", flag.ExitOnError)
barCmd = flag.NewFlagSet("bar", flag.ExitOnError)
)
Run Code Online (Sandbox Code Playgroud)
并使用循环迭代所有标志集,并注册通用标志,使用以下命令指向您的变量FlagSet.StringVar():
func setupCommonFlags() {
for _, fs := range []*flag.FlagSet{fooCmd, barCmd} {
fs.StringVar(
&required,
"required",
"",
"required for all commands",
)
}
}
Run Code Online (Sandbox Code Playgroud)
并在main()调用Parse()适当的标志集时,然后进行测试required:
func main() {
setupCommonFlags()
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])
}
if required == "" {
fmt.Println("-required is required for all commands")
}
}
Run Code Online (Sandbox Code Playgroud)
您可以通过创建标志集映射来改进上述解决方案,这样您就可以使用该映射来注册通用标志,并进行解析。
完整的应用程序:
var (
required string
fooCmd = flag.NewFlagSet("foo", flag.ExitOnError)
barCmd = flag.NewFlagSet("bar", flag.ExitOnError)
)
var subcommands = map[string]*flag.FlagSet{
fooCmd.Name(): fooCmd,
barCmd.Name(): barCmd,
}
func setupCommonFlags() {
for _, fs := range subcommands {
fs.StringVar(
&required,
"required",
"",
"required for all commands",
)
}
}
func main() {
setupCommonFlags()
cmd := subcommands[os.Args[1]]
if cmd == nil {
log.Fatalf("[ERROR] unknown subcommand '%s', see help for more details.", os.Args[1])
}
cmd.Parse(os.Args[2:])
fmt.Println(cmd.Name())
if required == "" {
fmt.Println("-required is required for all commands")
}
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
6985 次 |
| 最近记录: |