如何使用 cobra 调用默认子命令?

and*_*dig 6 go go-cobra

使用 cobra,如果在没有特定操作(但参数)的情况下调用我的应用程序,我想运行默认命令:

\n\n
// rootCmd represents the base command when called without any subcommands\nvar rootCmd = &cobra.Command{\n    Use:   "mbmd",\n    Short: "ModBus Measurement Daemon",\n    Long:  "Easily read and distribute data from ModBus meters and grid inverters",\n\n    Run: func(cmd *cobra.Command, args []string) {\n        run(cmd, args)\n    },\n}\n
Run Code Online (Sandbox Code Playgroud)\n\n

但是,由于根命令没有所有参数,因此子命令会失败,因为它现在显然知道子命令的参数:

\n\n
\xe2\x9d\xaf go run main.go -d sma:126@localhost:5061 --api 127.1:8081 -v\nError: unknown shorthand flag: \'d\' in -d\n
Run Code Online (Sandbox Code Playgroud)\n\n

与以下相反:

\n\n
\xe2\x9d\xaf go run main.go run -d sma:126@localhost:5061 --api 127.1:8081 -v\n2019/07/29 20:58:10 mbmd unknown version (unknown commit)\n
Run Code Online (Sandbox Code Playgroud)\n\n

如何以编程方式实例化/调用子命令?

\n

Von*_*onC 2

2021 年 3 月:您可以考虑第 823 期中提出的解决方法spf13/cobra

func subCommands() (commandNames []string) {
    for _, command := range cmd.Commands() {
        commandNames = append(commandNames, append(command.Aliases, command.Name())...)
    }
    return
}

func setDefaultCommandIfNonePresent() {
    if len(os.Args) > 1 { 
        potentialCommand := os.Args[1]
        for _, command := range subCommands() {
            if command == potentialCommand {
                return
            }
        }
        os.Args = append([]string{os.Args[0], "<default subcommand>"}, os.Args[1:]...)
    }

}

func main() {
    setDefaultCommandIfNonePresent()
    if err := cmd.Execute(); err != nil {
        zap.S().Error(err)
        os.Exit(1)
    }
}
Run Code Online (Sandbox Code Playgroud)

此处的区别在于,它len(os.Args) > 1在更改默认子命令之前检查 if 。

这意味着,如果在没有任何参数的情况下运行,它将打印默认的帮助命令(以及所有子命令)。
否则,如果提供任何参数,它将使用子命令。

因此,它将显示不带参数的主命令“ ”,如果提供了“ ”/“ ” help,则显示子命令的帮助。-h--help


或者(2021 年 10 月),来自PR 823作者

最新的解决方案如下:

main.go

func main() {
  // Define the default sub command 'defCmd' here. If user doesn't submit
  // using a default command, we'll use what is here.
  defCmd:="mydefaultcmd"
  cmd.Execute(defCmd)
}
Run Code Online (Sandbox Code Playgroud)

root.go

func Execute(defCmd string) {
  var cmdFound bool
  cmd :=rootCmd.Commands()

  for _,a:=range cmd{
    for _,b:=range os.Args[1:] {
      if a.Name()==b {
       cmdFound=true
        break
      }
    }
  }
  if !cmdFound {
    args:=append([]string{defCmd}, os.Args[1:]...)
    rootCmd.SetArgs(args)
  }
  if err := rootCmd.Execute(); err != nil {
    fmt.Println(err)
    os.Exit(1)
  }
}
Run Code Online (Sandbox Code Playgroud)