2 回答
TA贡献1943条经验 获得超7个赞
如果打算实现子命令,则不应调用 flag。解析())。
相反,请决定使用哪个子命令(就像您所做的那样),并仅调用其 FlagSet.Parse() 方法。os.Args[1]
是的,要使此操作有效,所有标志集都应包含公共标志。但是,只需注册一次(在一个地方)就很容易了。创建包级别变量:
var (
required string
fooCmd = flag.NewFlagSet("foo", flag.ExitOnError)
barCmd = flag.NewFlagSet("bar", flag.ExitOnError)
)
使用循环遍历所有标志集,并注册公共标志,使用FlagSet.StringVar()指向您的变量:
func setupCommonFlags() {
for _, fs := range []*flag.FlagSet{fooCmd, barCmd} {
fs.StringVar(
&required,
"required",
"",
"required for all commands",
)
}
}
并在调用适当的标志集,并在之后进行测试: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")
}
}
您可以通过创建标志集映射来改进上述解决方案,因此可以使用该映射注册公共标志,还可以执行解析。
完整应用:
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")
}
}
TA贡献2065条经验 获得超13个赞
将全局标志放在子命令之前:
go run . -required=x foo.
使用代替 :flag.Args()os.Args
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")
}
args := flag.Args() // everything after the -required flag, e.g. [foo, -foo-flag-1, -foo-flag-2, ...]
switch args[0] {
case "foo":
fooCmd.Parse(args[1:])
fmt.Println("foo")
case "bar":
barCmd.Parse(args[1:])
fmt.Println("bar")
default:
log.Fatalf("[ERROR] unknown subcommand '%s', see help for more details.", args[0])
}
}
如果要将所有标志放在一起,请在子命令之后编写一个帮助程序函数,该函数将公共标志添加到每个标志集:
var (
fooCmd = flag.NewFlagSet("foo", flag.ExitOnError)
barCmd = flag.NewFlagSet("bar", flag.ExitOnError)
)
type globalOpts struct {
required string
}
func main() {
var opts globalOpts
addGlobalFlags(fooCmd, &opts)
addGlobalFlags(barCmd, &opts)
if opts.required == "" {
fmt.Println("-required is required for all commands")
}
// ...
}
func addGlobalFlags(fs *flag.FlagSet, opts *globalOpts) {
fs.StringVar(
&opts.required,
"required",
"",
"required for all commands",
)
}
也许您还可以将这两种方法结合起来,使全局标志在任何位置工作。
- 2 回答
- 0 关注
- 81 浏览
添加回答
举报