2

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

// rootCmd represents the base command when called without any subcommands
var rootCmd = &cobra.Command{
    Use:   "mbmd",
    Short: "ModBus Measurement Daemon",
    Long:  "Easily read and distribute data from ModBus meters and grid inverters",

    Run: func(cmd *cobra.Command, args []string) {
        run(cmd, args)
    },
}

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

❯ go run main.go -d sma:126@localhost:5061 --api 127.1:8081 -v
Error: unknown shorthand flag: 'd' in -d

相对于:

❯ go run main.go run -d sma:126@localhost:5061 --api 127.1:8081 -v
2019/07/29 20:58:10 mbmd unknown version (unknown commit)

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

4

2 回答 2

2

这是另一个解决方案:

    cmd, _, err := rootCmd.Find(os.Args[1:])
    // default cmd if no cmd is given
    if err == nil && cmd.Use == rootCmd.Use && cmd.Flags().Parse(os.Args[1:]) != pflag.ErrHelp {
        args := append([]string{defaultCmd.Use}, os.Args[1:]...)
        rootCmd.SetArgs(args)
    }

    if err := rootCmd.Execute(); err != nil {
        fmt.Println(err)
        os.Exit(1)
    } 

替换defaultCmd为您想要默认的

cmd.Flags().Parse(os.Args[1:]) != pflag.ErrHelp如果未设置任何参数,此部分使帮助命令适用于 root 命令

于 2021-06-28T20:46:23.237 回答
1

2021 年 3 月:您可能会考虑使用spf13/cobra问题 823中提出的解决方法

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)
    }
}

这里的区别在于它len(os.Args) > 1在更改默认子命令之前检查是否。

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

因此,它将显示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)
}

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)
  }
}
于 2021-03-25T08:38:38.640 回答