命令行工具库cobra

CKeengolanggolang的常用库约 1437 字大约 5 分钟

作者:程序员CKeen
博客:http://ckeen.cnopen in new window

长期坚持做有价值的事!积累沉淀,持续成长,升维思考!希望把编码作为长期兴趣爱好😄


1. Cobra介绍

Cobra是一个用于创建强大的现代CLI应用程序的库。Cobra被用于许多go项目中,如Kubernetes, Hugo和Github CLI等。官方列举了使用cobra库open in new window的列表

Cobra主要特点:

  • 简单的子命令模式: 例如server start,app fetch,等等。
  • 完全兼容posix的命令行的选项标志(包括短版本和长版本)
  • 支持嵌套的子命令
  • 支持全局、本地和级联选项
  • 智能提醒 (当你输入app ser时,会提示你是否想输入的是app server)
  • 自动帮你生成命令和选项
  • 自动帮你做选项的识别,例如识别flag -h, --help
  • 自动生成应用程序在 bash 下命令自动完成功能
  • 为您的应用程序自动生成的man手册
  • 可以自定义 help 和 usage 信息

2. Cobra的三个重要概念

首先需要明确 3 个基本概念:

  • 命令(Command):需要执行的操作;
  • 参数(Arg):命令的参数,即要操作的对象;
  • 选项(Flag):命令选项可以调整命令的行为。

下面拿我们经常使用git的命令对举例

git clone -b develop https://xxxx.git

git config --global user.name "bettyaner"

git commit -m "xxxx"

上述的命令中

  • git是应用程序的名称,

  • clone/config/commit是一个命令(Command)或者子命令

  • -b/-m/--global为选项(Flag)

  • 选项后面的值为具体的参数(Arg)

3. 安装cobra库

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

使用的时候我们需要在项目中引用cobra

import (
	"github.com/spf13/cobra"
)

4. 使用cobra配置使用

我们先在cmd的目录下cobra.go创建cobra的根命令:

var author string

var rootCmd = &cobra.Command{
	Use:   "cobra [string to action]",
	Short: "cobra command tool",
	Long:  "cobra is a simple cli command tool",
	PersistentPreRun: func(cmd *cobra.Command, args []string) {
		log.Println("1. rootCmd PersistentPreRun")
	},
	PreRun: func(cmd *cobra.Command, args []string) {
		log.Println("2. rootCmd PreRun")
		//setup()
	},
	Run: func(cmd *cobra.Command, args []string) {
		log.Println("3. rootCmd Run, auth:" + author)
		run()
	},
	PostRun: func(cmd *cobra.Command, args []string) {
		log.Println("4. rootCmd PostRun")
	},
	PersistentPostRun: func(cmd *cobra.Command, args []string) {
		log.Println("5. rootCmd PersistentPostRun")
	},
}

func init(){
	rootCmd.PersistentFlags().StringVar(&author, "author", "CKeen", "Author name for copyright attribution")
	rootCmd.AddCommand(version.VersionCmd)
}

func run(){
	fmt.Println("go root cmd run")
}

func Execute() {
	if err := rootCmd.Execute(); err != nil {
		fmt.Fprintln(os.Stderr, err)
		os.Exit(1)
	}
}

我们在工程目录创建一个main.go,来调用上面的命令:

func main(){
	cmd.Execute()
}

我们将代码编译为cobra的执行文件:

go build -o cobra

我们可以看到生成了一个cobra的可执行文件,然后我们来查看一下使用帮助:

$./cobra --help

我们可以看到控制台打印了如下信息:

cobra is a simple cli command tool

Usage:
  cobra [string to action] [flags]
  cobra [command]

Available Commands:
  completion  Generate the autocompletion script for the specified shell
  help        Help about any command
  version     app version

Flags:
      --author string   Author name for copyright attribution (default "YOUR NAME")
  -h, --help            help for cobra

Use "cobra [command] --help" for more information about a command.

对比以上我们可以内容,我们知道:

  • Use的字段对应的内容为帮助中Usage的选项
  • Short是对指令的使用的简短描述
  • Long是对指令的使用的详细描述,这里我们可以看到执行./cobra --help第一行就答应的该描述信息
  • AddCommand添加子命令。这里我们通过rootCmd的AddCommand将子命令添加进来,子命令在Available Commands部分进行展示,这里我们添加了一个查看version的命令
  • PersistentFlags()解析参数选项。 这里我们使用rootCmd.PersistentFlags().StringVar(),函数来解析选项。这里我们可以看到StringVar函数可以绑定参数值,设置默认值,还支持描述信息。

我们在cmd/version的目录下来看下VersionCmd的代码:

var version string

var VersionCmd = &cobra.Command{
	Use:                        "version",
	Short:                      "app version",
	Long:                       "print this app current version",
	Example:                    "./cobra version",
	Args:                       nil,
	Version:                    "v1.0",
	PersistentPreRun: func(cmd *cobra.Command, args []string) {
		log.Println("1. versionCmd PersistentPreRun")
	},
	PreRun: func(cmd *cobra.Command, args []string) {
		log.Println("2. versionCmd PreRun")
	},
	Run: func(cmd *cobra.Command, args []string) {
		log.Println("3. versionCmd Run")
	},
	PostRun: func(cmd *cobra.Command, args []string) {
		log.Println("4. versionCmd PostRun")
	},
	PersistentPostRun: func(cmd *cobra.Command, args []string) {
		log.Println("5. versionCmd PersistentPostRun")
	},
}

func init(){
	VersionCmd.PersistentFlags().StringVarP(&version, "v", "v", "v.10", "app version")
}

我们可以使用子命令的help来查看

$./cobra version --help

我们可以看到打印了如下部分:

print this app current version

Usage:
  cobra version [flags]

Examples:
 ./cobra version

Flags:
  -h, --help       help for version
  -v, --v string   app version (default "v.10")
      --version    version for version

Global Flags:
      --author string   Author name for copyright attribution (default "YOUR NAME")

我们可以看到这里的描述跟rootCmd查不多,也是配置的那几个参数,这里我们多配置了一个Example示例,这个Example在help打印中也展示出来了。

同时这里可以看到还支持Global Flags,这个参数是我们在rootCmd中进行配置的,这里说明我们这里可以使用rootCmd的中的flag值。

5. cobra中command执行

首先我们执行一下上一节中编译的cobra的可执行文件,同时传入--author的flag选项

$./cobra --author CKeen

我们可以看到如下打印信息:

2022/07/10 01:01:41 1. rootCmd PersistentPreRun
2022/07/10 01:01:41 2. rootCmd PreRun
2022/07/10 01:01:41 3. rootCmd Run, auth:CKeen
go root cmd run
2022/07/10 01:01:41 4. rootCmd PostRun
2022/07/10 01:01:41 5. rootCmd PersistentPostRun

我们看到author选项设置了值,在rootCmd的Run方法中打印出来了,同时我们可以看到Command执行提供如下的回调执行顺序:

1. PersistentPreRun2. PreRun3.Run4.PostRun5.PersistentPostRun

我们一般将主要执行的业务逻辑放到Run中去执行,PreRun和PostRun可以做一些预处理的工作和执行后的清尾工作。

6.参考资料

cobra源码github: https://github.com/spf13/cobraopen in new window

cobra的包介绍: https://pkg.go.dev/github.com/spf13/cobraopen in new window