基于cobra的go语言命令行解析器

ubuntu安装cobra

$ sudo apt install cobra
Reading package lists... Done
Building dependency tree       
Reading state information... Done
The following NEW packages will be installed:
  cobra
0 upgraded, 1 newly installed, 0 to remove and 0 not upgraded.
Need to get 2,873 kB of archives.
After this operation, 9,495 kB of additional disk space will be used.
Get:1 http://mirrors.tuna.tsinghua.edu.cn/ubuntu focal/universe amd64 cobra amd64 0.0.5-1 [2,873 kB]
Fetched 2,873 kB in 2s (1,272 kB/s) 
Selecting previously unselected package cobra.
(Reading database ... 188150 files and directories currently installed.)
Preparing to unpack .../cobra_0.0.5-1_amd64.deb ...
Unpacking cobra (0.0.5-1) ...
Setting up cobra (0.0.5-1) ...
Processing triggers for man-db (2.9.1-1) ...

Go在项目中使用cobra

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

使用cobra创建项目
创建项目建议使用Go module模式,首先,创建一个go module项目,项目名称为arsenal

root@curtis-Aspire-E5-471G:/home/curtis/go_env/arsenal# go mod init arsenal
go: creating new go.mod: module arsenal
root@curtis-Aspire-E5-471G:/home/curtis/go_env/arsenal# ll
total 12
drwxr-xr-x 2 root root 4096 1118 21:25 ./
drwxr-xr-x 6  644 root 4096 1118 21:25 ../
-rw-r--r-- 1 root root   24 1118 21:25 go.mod

arsenal目录中添加cobra项目。

root@curtis-Aspire-E5-471G:/home/curtis/go_env/arsenal# cobra init --pkg-name arsenal
Your Cobra applicaton is ready at
/home/curtis/go_env/arsenal

root@curtis-Aspire-E5-471G:/home/curtis/go_env/arsenal# tree .
.
├── cmd
│   └── root.go	# 最顶层的命令rootCmd
├── go.mod
├── LICENSE	 # license信息
└── main.go

编译之前下载几个依赖包

root@curtis-Aspire-E5-471G:/home/curtis/go_env/arsenal# go build
cmd/root.go:24:3: no required module provides package github.com/mitchellh/go-homedir; to add it:
	go get github.com/mitchellh/go-homedir
cmd/root.go:22:3: no required module provides package github.com/spf13/cobra; to add it:
	go get github.com/spf13/cobra
cmd/root.go:25:3: no required module provides package github.com/spf13/viper; to add it:
	go get github.com/spf13/viper

# 执行生成的可执行文件
root@curtis-Aspire-E5-471G:/home/curtis/go_env/arsenal# ./arsenal 
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.

编译出来的二进制文件arsenal默认打印的信息是怎么来的?来自rootCmd命令的长描述信息。

// cmd/root.go
// rootCmd represents the base command when called without any subcommands
var rootCmd = &cobra.Command{
  Use:   "arsenal",
  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) { },
}

尝试修改rootCmd命令的描述信息。

var rootCmd = &cobra.Command{
        Use:   "arsenal",
        Short: "A brief description of your application",
        Long: "This is long description of your application",	// 出现在-h的帮助信息中
        // Uncomment the following line if your bare application
        // has an action associated with it:
        //      Run: func(cmd *cobra.Command, args []string) { },
}

执行命令

root@curtis-Aspire-E5-471G:/home/curtis/go_env/arsenal# ./arsenal 
This is long description of your application

添加子命令,比如说添加一个版本信息

root@curtis-Aspire-E5-471G:/home/curtis/go_env/arsenal# cobra add version
version created at /home/curtis/go_env/arsenal
root@curtis-Aspire-E5-471G:/home/curtis/go_env/arsenal# tree .
.
├── arsenal
├── cmd
│   ├── root.go
│   └── version.go	# 新添加了一个versoin.go
├── go.mod
├── go.sum
├── LICENSE
└── main.go

# go build编译之后执行命令
root@curtis-Aspire-E5-471G:/home/curtis/go_env/arsenal# ./arsenal 
This is long description of your application

Usage:
  arsenal [command]

Available Commands:
  completion  Generate the autocompletion script for the specified shell
  help        Help about any command	# 添加的子命令
  version     This short information about version	# 可以看到version子命令的短描述信息

Flags:
      --config string   config file (default is $HOME/.arsenal.yaml)
  -h, --help            help for arsenal
  -t, --toggle          Help message for toggle

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

# 执行了注册的Run 函数,该函数打印了信息version called
root@curtis-Aspire-E5-471G:/home/curtis/go_env/arsenal# ./arsenal version 
version called

# -h 信息可以看到version 命令的长信息
root@curtis-Aspire-E5-471G:/home/curtis/go_env/arsenal# ./arsenal version -h
This long information about version

Usage:
  arsenal version [flags]

Flags:
  -h, --help   help for version

Global Flags:
      --config string   config file (default is $HOME/.arsenal.yaml)

如何把命令绑定到父命令中,可以无限制的往下添加,但是需要注意的是每个cobra.command结构体只能指向一个parent cobra.command

# 不做任何处理
root@curtis-Aspire-E5-471G:/home/curtis/go_env/arsenal# cobra add cpu
cpu created at /home/curtis/go_env/arsenalroot@curtis-Aspire-E5-471G:/home/curtis/go_env/arsenal# 
root@curtis-Aspire-E5-471G:/home/curtis/go_env/arsenal# tree .
.
├── arsenal
├── cmd
│   ├── cpu.go
│   ├── root.go
│   └── version.go
├── go.mod
├── go.sum
├── LICENSE
└── main.go

1 directory, 8 files
root@curtis-Aspire-E5-471G:/home/curtis/go_env/arsenal# go build
root@curtis-Aspire-E5-471G:/home/curtis/go_env/arsenal# ./arsenal 
This is long description of your application

Usage:
  arsenal [command]

Available Commands:
  completion  Generate the autocompletion script for the specified shell
  cpu         A brief description of your command
  help        Help about any command
  version     This short information about version

Flags:
      --config string   config file (default is $HOME/.arsenal.yaml)
  -h, --help            help for arsenal
  -t, --toggle          Help message for toggle

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

添加子命令
将上述cpu子命令添加到version下修改之后。

// 只需要将cpuCmd添加到versionCmd之下就可以了。
func init() {
	// 使用cobra add默认将命令添加到rootCmd
	// 可以尝试修改添加到version cmd之下
	versionCmd.AddCommand(cpuCmd)

	// Here you will define your flags and configuration settings.

	// Cobra supports Persistent Flags which will work for this command
	// and all subcommands, e.g.:
	// cpuCmd.PersistentFlags().String("foo", "", "A help for foo")

	// Cobra supports local flags which will only run when this command
	// is called directly, e.g.:
	// cpuCmd.Flags().BoolP("toggle", "t", false, "Help message for toggle")
}
root@curtis-Aspire-E5-471G:/home/curtis/go_env/arsenal# ./arsenal version -h
This long information about version

Usage:
  arsenal version [flags]
  arsenal version [command]

Available Commands:
  cpu         A brief description of your command	# 子命令添加成功

Flags:
  -h, --help   help for version

Global Flags:
      --config string   config file (default is $HOME/.arsenal.yaml)

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

选项的接收与处理

var versionCmd = &cobra.Command{
	Use:   "version",
	Short: "This short information about version",
	Long:  "This long information about version",

	Run: func(cmd *cobra.Command, args []string) {
		fmt.Println("version called")
		// 各个选项参数获取
		auther, err := cmd.Flags().GetString("auther")
		if err != nil {
			fmt.Println("请输入正确的作者信息")
			return
		}

		fmt.Println("作者是: ", auther)
	},
}

func init() {
	rootCmd.AddCommand(versionCmd)

	// Here you will define your flags and configuration settings.

	// Cobra supports Persistent Flags which will work for this command
	// and all subcommands, e.g.:
	// versionCmd.PersistentFlags().String("foo", "", "A help for foo")

	// Cobra supports local flags which will only run when this command
	// is called directly, e.g.:
	// versionCmd.Flags().BoolP("toggle", "t", false, "Help message for toggle")
	// 添加version参数auther,a为别名,默认值为cutis
	versionCmd.Flags().StringP("auther", "a", "curtis", "The auther name")
	// 添加version参数percent,p为别名,默认值为60%
	versionCmd.Flags().StringP("percent", "p", "60%", "The percent of cpu")
}
root@curtis-Aspire-E5-471G:/home/curtis/go_env/arsenal# ./arsenal version -h
This long information about version

Usage:
  arsenal version [flags]
  arsenal version [command]

Available Commands:
  cpu         A brief description of your command

Flags:
  -a, --auther string    The auther name (default "curtis")
  -h, --help             help for version
  -p, --percent string   The percent of cpu (default "60%")

Global Flags:
      --config string   config file (default is $HOME/.arsenal.yaml)

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

选项常见的类型

  • 布尔值
  • 数字(各种整形,浮点数等)
  • 字符串
  • 其他高级类型

选项的帮助信息

命令自动补全补全功能
从上面构建的工程来看,cobra已经把自动补全的功能默认添加到项目中,使用方法如下所示。

root@curtis-Aspire-E5-471G:/home/curtis/go_env/arsenal# ./arsenal completion bash -h 
Generate the autocompletion script for the bash shell.

This script depends on the 'bash-completion' package.
If it is not installed already, you can install it via your OS's package manager.

To load completions in your current shell session:

	source <(arsenal completion bash)	# 只有在当前shell终端生效

To load completions for every new session, execute once:

#### Linux:

	arsenal completion bash > /etc/bash_completion.d/arsenal	# 永久生效

#### macOS:

	arsenal completion bash > $(brew --prefix)/etc/bash_completion.d/arsenal

# 需要重新开启新的终端才会生效
You will need to start a new shell for this setup to take effect.

Usage:
  arsenal completion bash

Flags:
  -h, --help              help for bash
      --no-descriptions   disable completion descriptions

Global Flags:
      --config string   config file (default is $HOME/.arsenal.yaml)

启用自动补全功能之后,使用tab命令没有自动补全,报错如下。

root@curtis-Aspire-E5-471G:/home/curtis/go_env/arsenal# source <(./arsenal completion bash)
root@curtis-Aspire-E5-471G:/home/curtis/go_env/arsenal# ./arsenal ver_get_comp_words_by_ref: command not found
_get_comp_words_by_ref: command not found
_get_comp_words_by_ref: command not found

可能原因是有可能没有安装bash-completion包,安装方法即开启命令自动补全如下所示。

# 安装bash-completion包
$ sudo apt install bash-completion

# 启用completion功能
root@curtis-Aspire-E5-471G:/home/curtis/go_env/arsenal# source /usr/share/bash-completion/bash_completion
root@curtis-Aspire-E5-471G:/home/curtis/go_env/arsenal# source <(./arsenal completion bash)

# 可以使用tab键自动补全命令
root@curtis-Aspire-E5-471G:/home/curtis/go_env/arsenal# ./arsenal version cpu

自定义配置文件中读取cli命令行相关参数
常见的配置文件类型有json,yaml从上述注册的命令来看,还有一个可选项,那就是从配置文件中读取cli命令行相关参数。用cobra命令初始化的模块默认的文件格式为yaml。

Global Flags:
      --config string   config file (default is $HOME/.arsenal.yaml)

获取命令行中的所有flags

// 返回指向Flag结构体的指针f
func checkFlags(f *pflag.Flag) {
	fmt.Println(f.Name)
}

// 访问命令行中已经输入的flags
func main(){
  flagset.Visit(checkFlags);
}

// 访问所有定义的flags
func main(){
  flagset.VisitAll(checkFlags);
}

示例代码:

func checkFlags(f *pflag.Flag) {
	fmt.Println(f.Name)
}

// cpuCmd represents the cpu command
var cpuCmd = &cobra.Command{
	Use:   "cpu",
	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("cpu called")

		// flags := cmd.Flags()
		// fmt.Println(flags)

		cmd.Flags().Visit(checkFlags)
	},
}

成功解析当前命令行输入的所有flags,想要获取flags所对应的值,cmd.Flags()下有对应的方法。

curtis@curtis-Aspire-E5-471G:~/go_env/arsenal$ ./arsenal version cpu -p ./ll -a curtis
cpu called
author
file-name

获取某个command的帮助信息

func getUsageInfo(cmd *cobra.command, args []string) {
	usageInfo := cmd.Flags().FlagUsages()
	fmt.Println(usageInfo)
}

获取Flagset的所有信息

flagInfo := cmd.Flags()
fmt.Println(flagInfo )

代码实例

// cpuCmd represents the cpu command
var cpuCmd = &cobra.Command{
	Use:   "cpu",
	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("cpu called")

		flags := cmd.Flags()
		fmt.Println(flags)
	},
}

打印信息如下,为结构体FlagSet所对应的详细信息。

&{<nil> true {false} cpu true map[author:0xc0000bbae0 file-name:0xc0000bba40] [0xc0000bba40 0xc0000bbae0] [] map[author:0xc0000bbae0 config:0xc0000bbb80 file-name:0xc0000bba40 help:0xc0001380a0] [0xc0000bba40 0xc0000bbae0 0xc0000bbb80 0xc0001380a0] [0xc0000bbae0 0xc0000bbb80 0xc0000bba40 0xc0001380a0] map[97:0xc0000bbae0 104:0xc0001380a0 112:0xc0000bba40] [] -1 0 0xc00009b800 true <nil> []}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值