Cobra介绍

Cobra 是一个用于创建强大的现代 CLI 应用程序的库。几乎包含了你所需要的所有元素。

Cobra 用于许多 Go 项目,例如Kubernetes、Docker、GitHub CLI、Hugo等等。

Cobra提供:

  • 简单的基于子命令的 CLI:app server、app fetch等。
  • 完全符合 POSIX 的标志(包括短版和长版)
  • 嵌套子命令
  • 全局、本地和级联标志
  • 明智的建议(app srver…你的意思是app server?)
  • 命令和标志的自动帮助生成
  • 子命令的分组帮助
  • -h,–help等的自动帮助标志识别
  • 为您的应用程序自动生成 shell 自动补全的功能(bash、zsh、fish、powershell)
  • 为您的应用程序自动生成的手册页(man page)
  • 命令别名,这样您就可以在不破坏它们的情况下进行更改
  • 定义您自己的帮助、使用等的灵活性。
  • 可选与viper无缝集成,用于 12 要素应用程序(viper是作者的另一个项目,用来给go语言程序提供配置解决方案,可以将cobra和viper结合使用)

Cobra安装

cobra提供了用于go get安装的最新版本的库。

go get -u github.com/spf13/cobra@latest

同时,Cobra提供了一个方便的命令行程序生成器cobra-cli,后续我们会使用cobra-cli来自动生成模板,简化我们的工作。因此也需要安装它。

go install github.com/spf13/cobra-cli@latest

需要注意的是,Go 会自动将cobra-cli安装在你的GOPATH/bin目录中,因此你要确保GOPATH/bin被你添加到了环境变量中。否则你无法使用cobra-cli程序。以Debian系统为例,你可以通过go env|grep GOPATH命令来查看你的GOPATH,然后将GOPATH/bin添加到~/.bashrc文件中,例如:

export PATH=$PATH:/home/zy/go/bin

在~/.bashrc中添加上面这行之后,执行下面的命令,使其生效。

source ~/.bashrc

Cobra使用

Cobra提供了一个生成器(cobra-cli),可以用来初始化你的命令行程序。这是将 Cobra 整合到您的应用程序中的最简单方法。当然你也可以手动来创建自己的命令行程序。cobra-cli只是帮助你简化了创建过程。下面使用cobra-cli生成器来创建我们自己的命令行程序。

  1. 创建一个新目录并初始化go mod

    mkdir mycmd
    cd mycmd
    go mod init mycmd

  2. 使用cobra-cli来初始化一个项目

    确保你以及按照安装步骤安装了cobra以及cobra-cli,并将cobra-cli添加到了环境变量中。在mycmd目录下执行下面的命令。

     cobra-cli init
    

    执行该命令会在当前目录下生成cmd目录,main.go等文件。现在尝试运行一下自动生成的命令行程序。

     go run main.go
    

    确保可以成功运行即可

  3. 修改自动生成的程序为你自己的功能

    使用cobra-cli生成以后,目录结构如下所示。

     .├── cmd│   └── root.go├── go.mod├── go.sum├── LICENSE└── main.go
    

    我们来看一下自动生成的文件中的内容。由于我们在自动生成的时候,没有使用-l(–license)参数,因此自动生成的LICENSE文件为空。main.go文件和cmd目录下的root.go才是我们关心的重点。

    // main.go
    package mainimport "mycmd/cmd"func main() {cmd.Execute()
    }
    

    main.go文件非常简单,就只是简单的初始化cobra。让我们再来看看root.go文件。

    // root.go
    package cmdimport ("os""github.com/spf13/cobra"
    )// rootCmd represents the base command when called without any subcommands
    var rootCmd = &cobra.Command{Use:   "mycmd",Short: "A brief description of your application",Long: `A longer description that spans multiple lines and likely contains
    examples and usage of using your application. For example:Cobra is a CLI library for Go that empowers applications.
    This application is a tool to generate the needed files
    to quickly create a Cobra application.`,// Uncomment the following line if your bare application// has an action associated with it:// Run: func(cmd *cobra.Command, args []string) { },
    }// Execute adds all child commands to the root command and sets flags appropriately.
    // This is called by main.main(). It only needs to happen once to the rootCmd.
    func Execute() {err := rootCmd.Execute()if err != nil {os.Exit(1)}
    }func init() {// Here you will define your flags and configuration settings.// Cobra supports persistent flags, which, if defined here,// will be global for your application.// rootCmd.PersistentFlags().StringVar(&cfgFile, "config", "", "config file (default is $HOME/.mycmd.yaml)")// Cobra also supports local flags, which will only run// when this action is called directly.rootCmd.Flags().BoolP("toggle", "t", false, "Help message for toggle")
    }
    

    首先是定义一个cobra.Command指针类型的变量rootCmd,其中定义了Use,Short, Long字段的值,关于这些字段的含义,可以通过查看Command结构体的注释来了解。另外就是在init函数中,给rootCmd添加了一个标志toggle。Execute()函数就是我们在main.go文件中调用的函数。现在,我们来修改一下root.go程序。让其展示我们的功能。

    // 修改后的root.go
    package cmdimport ("os""github.com/spf13/cobra"
    )var rootCmd = &cobra.Command{Use:   "test",Short: "A test programming",Long:  "A test programming",Run: func(cmd *cobra.Command, args []string) {cmd.Help() // 当不带有任何参数或者标志执行程序的时候,输出help},
    }func Execute() {err := rootCmd.Execute()if err != nil {os.Exit(1)}
    }func init() {rootCmd.CompletionOptions.DisableDefaultCmd = true // 禁用Completion命令rootCmd.Version = "0.0.1"                         // 设置version
    }
    

    执行main.go,输出如下所示:

     A test programmingUsage:test [flags]Flags:-h, --help      help for test-v, --version   version for test
    

    我们加上标志-v(go run main.go -v)再来执行一次,输出如下:

     test version 0.0.1
    

    我们通过rootCmd.CompletionOptions.DisableDefaultCmd = true这行代码禁用掉了completion命令。它可以提供生成shell completion,来给予命令补全等功能。详细的文档可以查看Generating shell completions

  4. 增加新命令

    初始化 cobra 应用程序后,你可以继续使用cobra-cli向应用程序添加其他命令。执行此操作的命令是cobra-cli add [command],例如:

     cobra-cli add start
    

    执行该命令之后,你会发现在cmd目录下生成了一个名为start.go的文件,内容如下所示:

    // start.go
    package cmdimport ("fmt""github.com/spf13/cobra"
    )// startCmd represents the start command
    var startCmd = &cobra.Command{Use:   "start",Short: "A brief description of your command",Long: `A longer description that spans multiple lines and likely contains examples
    and usage of using your command. For example:Cobra is a CLI library for Go that empowers applications.
    This application is a tool to generate the needed files
    to quickly create a Cobra application.`,Run: func(cmd *cobra.Command, args []string) {fmt.Println("start called")},
    }func init() {rootCmd.AddCommand(startCmd)// Here you will define your flags and configuration settings.// Cobra supports Persistent Flags which will work for this command// and all subcommands, e.g.:// startCmd.PersistentFlags().String("foo", "", "A help for foo")// Cobra supports local flags which will only run when this command// is called directly, e.g.:// startCmd.Flags().BoolP("toggle", "t", false, "Help message for toggle")
    }
    

    这段代码也很容易理解,startCmd这个结构体指针中配置了结构体中的一些参数;init函数中rootCmd.AddCommand(startCmd)这行代码将startCmd作为一个命令添加到rootCmd中。此时默认的父级就是rootCmd。还可以使用-p标志直接指定父命令。例如:

     cobra-cli add time -p "startCmd"
    

    需要注意的是:“指定父级时,请确保与代码中使用的变量名匹配”。这样生成的time.go文件如下所示:

    // time.go
    package cmdimport ("fmt""github.com/spf13/cobra"
    )// timeCmd represents the time command
    var timeCmd = &cobra.Command{Use:   "time",Short: "A brief description of your command",Long: `A longer description that spans multiple lines and likely contains examples
    and usage of using your command. For example:Cobra is a CLI library for Go that empowers applications.
    This application is a tool to generate the needed files
    to quickly create a Cobra application.`,Run: func(cmd *cobra.Command, args []string) {fmt.Println("time called")},
    }func init() {startCmd.AddCommand(timeCmd)// Here you will define your flags and configuration settings.// Cobra supports Persistent Flags which will work for this command// and all subcommands, e.g.:// timeCmd.PersistentFlags().String("foo", "", "A help for foo")// Cobra supports local flags which will only run when this command// is called directly, e.g.:// timeCmd.Flags().BoolP("toggle", "t", false, "Help message for toggle")
    }
    

    可以看到init函数中是把timeCmd添加到startCmd,而不是之前的start命令,会把startCmd添加到rootCmd。这样,我们可以这样执行命令。

     go run main.go start time
    

    还有一点需要注意,那就是命令的命令需要遵循驼峰命名法。

  5. 编辑 cmd 中的文件并为您的应用程序自定义它们
    在第三步的时候,我们已经介绍过了简单的方式来自定义它们。下面对command中常用的参数做一个说明。

    参数 含义
    Use 显示用法,例如:add [-F file
    Short 是help中输出的简短描述
    Long 是help中输出的长描述
    Example 如何使用该命令的示例
    Aliases 别名数组,用来给命令起别名
    GroupID 该子命令在其父命令的help标志输出中分组时使用的组id
    Arg 参数
    Version 版本标志。如果该值非空,并且命令没有定义Version标志,则Version标志将被添加到命令中,如果定义了Version标志,将打印Version变量的内容。如果命令没有定义一个简写的“v”标志,也将添加简写的“v”标志。
    Run 通常是实际的功函数,即使用该命令的时候会调用的函数。函数原型func(cmd *Command, args []string)
    RunE 和Run类似,只不过会返回一个error,函数原型func(cmd *Command, args []string) error

使用标志

由于标志是在不同的位置定义和使用的,我们需要在外部定义一个具有正确范围的变量来分配标志以使用。例如:

var Verbose bool
var Source string

分配标志有两种不同的方法。

持久标志

标志可以是“持久的”,这意味着该标志将可用于分配给它的命令以及该命令下的每个命令。对于全局标志,将标志分配为根上的持久标志。

rootCmd.PersistentFlags().BoolVarP(&Verbose, "verbose", "v", false, "verbose output")

本地标志

也可以在本地分配一个标志,该标志仅适用于该特定命令。

localCmd.Flags().StringVarP(&Source, "source", "s", "", "Source directory to read from")

父命令上的本地标志

默认情况下,Cobra 仅解析目标命令上的本地标志,而忽略父命令上的任何本地标志。通过启用Command.TraverseChildren,Cobra 将在执行目标命令之前解析每个命令上的本地标志。

command := cobra.Command{
Use: "print [OPTIONS] [COMMANDS]",
TraverseChildren: true,
}

必需的标志

默认情况下,标志是可选的。相反,如果您希望您的命令在未设置标志时报告错误,请将其标记为必需:

rootCmd.Flags().StringVarP(&Region, "region", "r", "", "AWS region (required)")
rootCmd.MarkFlagRequired("region")

或者,对于持久标志:

rootCmd.PersistentFlags().StringVarP(&Region, "region", "r", "", "AWS region (required)")
rootCmd.MarkPersistentFlagRequired("region")

标记组

如果您有不同的标志必须一起提供(例如,如果他们提供–username标志,他们也必须提供–password标志),那么 Cobra 可以强制执行该要求:

rootCmd.Flags().StringVarP(&u, "username", "u", "", "Username (required if password is set)")
rootCmd.Flags().StringVarP(&pw, "password", "p", "", "Password (required if username is set)")
rootCmd.MarkFlagsRequiredTogether("username", "password")

如果它们表示互斥选项,例如将输出格式指定为其中一个–json或–yaml但从不同时指定,您还可以防止同时提供不同的标志:

rootCmd.Flags().BoolVar(&u, "json", false, "Output in JSON")
rootCmd.Flags().BoolVar(&pw, "yaml", false, "Output in YAML")
rootCmd.MarkFlagsMutuallyExclusive("json", "yaml")

位置和自定义参数

可以使用Args字段来指定位置参数的验证Command。内置以下验证器:

  • 参数数量:

    • NoArgs- 如果有任何位置参数,则报告错误。
    • ArbitraryArgs- 接受任意数量的参数。
    • MinimumNArgs(int)- 如果提供的位置参数少于 N 个,则报告错误。
    • MaximumNArgs(int)- 如果提供的位置参数超过 N 个,则报告错误。
    • ExactArgs(int)- 如果不完全有 N 个位置参数,则报告错误。
    • RangeArgs(min, max)min- 如果 args 的数量不在 和 之间,则报告错误max。
  • 参数内容:

    如果在OnlyValidArgsValidArgs字段中未指定任何位置参数,则报告错误Command,可以选择将其设置为位置参数的有效值列表。如果Args未定义或nil,则默认为ArbitraryArgs。

此外,MatchAll(pargs …PositionalArgs)可以将现有检查与任意其他检查相结合。例如,如果你想在不完全有 N 个位置参数的情况下报告错误,或者如果有任何位置参数不在 的ValidArgs字段中Command,你可以调用and MatchAll,如下所示:ExactArgsOnlyValidArgs

var cmd = &cobra.Command{Short: "hello",Args: cobra.MatchAll(cobra.ExactArgs(2), cobra.OnlyValidArgs),Run: func(cmd *cobra.Command, args []string) {fmt.Println("Hello, World!")},
}

另外,你可以设置任何满足func(cmd *cobra.Command, args []string) error. 例如:

var cmd = &cobra.Command{Short: "hello",Args: func(cmd *cobra.Command, args []string) error {// Optionally run one of the validators provided by cobraif err := cobra.MinimumNArgs(1)(cmd, args); err != nil {return err}// Run the custom validation logicif myapp.IsValidColor(args[0]) {return nil}return fmt.Errorf("invalid color specified: %s", args[0])},Run: func(cmd *cobra.Command, args []string) {fmt.Println("Hello, World!")},
}

关于cobra库的更多使用指南,请参考该项目的官方文档

参考资料

  • https://github.com/spf13/cobra/blob/main/README.md

go命令行库-cobra相关推荐

  1. Go命令行库Cobra的使用

    点击上方"朱小厮的博客",选择"设为星标" 回复"1024"获取独家整理的学习资料 欢迎跳转到本文的原文链接:https://honeypp ...

  2. cobra mysql_golang中命令行库cobra的使用方法示例

    简介 Cobra既是一个用来创建强大的现代CLI命令行的golang库,也是一个生成程序应用和命令行文件的程序.下面是Cobra使用的一个演示: Cobra提供的功能 简易的子命令行模式,如 app ...

  3. Python 命令行库的大乱

    当你想实现一个命令行程序时,或许第一个想到的是用 Python 来实现.比如 CentOS 上大名鼎鼎的包管理工具 yum 就是基于 Python 实现的. 而 Python 的世界中有很多命令行库, ...

  4. Google 开源的 Python 命令行库:fire 实现 git 命令

    一.前言 在前面三篇介绍 fire 的文章中,我们全面了解了 fire 强大而不失简洁的能力.按照惯例,我们要像使用 argparse.docopt 和 click 一样使用 fire 来实现 git ...

  5. 酷玩Go命令行工具—Cobra

    不知大家有没有在使用Git命令.Linux的yum命令.Go命令.Maven命令的时候感觉到非常的酷,比如你刚刚拿到一个Go的开源项目,初始化时只需要输入go mod tidy进行对依赖的下载,或者是 ...

  6. Golang — 命令行工具cobra

    文章目录 Cobra 特性 概念 Command Flag 全局标识(Persistent Flags) 局部标识(Local Flags) Run Hooks Cobra Cobra是一个用于Go语 ...

  7. Go语言命令行库urfave/cli简介

    很多用Go写的命令行程序都用了urfave/cli这个库,包括geth,有必要简单了解一下. 用C写过命令行程序的人应该都不陌生,我们需要根据argc/argv一个个地解析命令行参数,调用不同的函数, ...

  8. golang开发命令行工具-cobra

    包地址:go get -u github.com/spf13/cobra/cobra go mod init blog go get -u github.com/spf13/cobra/cobra 具 ...

  9. 命令行工具cobra的使用

    安装cobra go get -v github.com/spf13/cobra/cobra 切换到GOPATH的src目录下并创建一个新文件夹:demo cd $GOPATH/src mkdir d ...

最新文章

  1. qu.la网站上的小说爬取
  2. 【计算理论】计算复杂性 ( 计算理论内容概览 | 计算问题的有效性 | 时间复杂性度量 | 输入表示 | 时间复杂度 )
  3. Go的go-sql-driver/mysql
  4. 1006:A+B问题
  5. java注解---@SuppressWarnings
  6. iphone-命令行编译之--xcodebuild
  7. 全国计算机一级知识题及答案解析,全国计算机等级考试一级试题库大全完整版附参考答案...
  8. c++面向对象高级编程 学习十三 数量不定的模板参数,auto,for
  9. php分流短信服务商,使用第三方短信服务商云片发送短信(php样例)
  10. js动态生产table、Div、select
  11. html模板查询,前台模板查找
  12. ADNI数据集相关知识整理
  13. Poisson方程的五点差分格式例题求解-Matlab实现
  14. SFM方向开源软件COLMAP代码分析
  15. 信息化与业务流程再造
  16. Python产生100个1—100的随机数放入列表Num中,输出列表中的数,然后将它们排序,并输出排序结果。
  17. 第31章 TIM—基本定时器—零死角玩转STM32-F429系列
  18. Beetl开源那些事3
  19. Extjs中利用combobox实现全国省市级联
  20. 长沙理工大学第十二届ACM大赛-重现赛 L - 选择困难症

热门文章

  1. Android 内置可卸载应用报错
  2. 使用Qemu模拟vexpress-a9搭建模拟开发板
  3. C语言中的 static变量、static函数
  4. Java学习笔记:案例发送工资条到邮箱
  5. 哪款耳机音质好又耐用?音质最好的耳机排名
  6. plus仿element库
  7. 超级简单的自动刷新_立邦开启“天猫超级品牌日”,背后意图究竟是什么?
  8. echarts 自适应屏幕 主题颜色 自动缩放选框 多图展示 自定义toolTip
  9. 使用原生BeetlSql
  10. 苹果8plus什么用计算机,【苹果iPhone8Plus评测】iOS 11:基础分满分后它要做附加题-中关村在线...