无论是Openstack还是Docker都有一个漂亮的命令行工具,Openstack的命令行工具主要使用的是Python的argparse库,至于Docker的CLI的实现还没看,但是今天看到了一个在Golang中 用于构建像Docker命令行风格的一个库:cobra
cobra简介
Cobra既是一个用来创建强大的现代CLI命令行的golang库,也是一个生成程序应用和命令行文件的程序。
它提供的功能有:
- 简易的子命令行模式,如 app server, app fetch等等
- 完全兼容posix命令行模式
- 嵌套子命令subcommand
- 支持全局,局部,串联flags
- 使用Cobra很容易的生成应用程序和命令,使用cobra create appname和cobra add cmdname
- 如果命令输入错误,将提供智能建议,如 app srver,将提示srver没有,是否是app server
- 自动生成commands和flags的帮助信息
- 自动生成详细的help信息,如app help
- 自动识别-h,–help帮助flag
- 自动生成应用程序在bash下命令自动完成功能
- 自动生成应用程序的man手册
- 命令行别名
- 自定义help和usage信息
- 可选的紧密集成的viper apps
从功能上看完全超越了argparse, 下面将做一个简单的测试,体验下cobra的强大
安装
安装cobra需要翻墙,我的环境是Mac,使用ss + polipo来提供https的方向代理。我的代理端口在8123,所以命令行是这样的
$https_proxy=localhost:8123 go get -v github.com/spf13/cobra/cobra
安装完成后可以看到cobra的一些帮助信息
maojun@maojun-mbp$ cobra -h
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.
Usage:
cobra [command]
Available Commands:
add Add a command to a Cobra Application
init Initialize a Cobra Application
Flags:
-a, --author string Author name for copyright attribution (default "YOUR NAME")
--config string config file (default is $HOME/.cobra.yaml)
-l, --license license Name of license for the project (can provide license in config)
-b, --projectbase string base project directory, e.g. github.com/spf13/
--viper Use Viper for configuration (default true)
Use "cobra [command] --help" for more information about a command.
使用
接下来将使用cobra构建一个不带子命令的CLI和带子命令的CLI
初始化
我们可以通过cobra提供的init命令来生成CLI的框架代码,因此切换到GOPATH/src下面,初始CLI框架
maojun@maojun-mbp$ cobra init demo
Your Cobra application is ready at
/Users/maojun/GoWorkDir/src/demo
Give it a try by going there and running `go run main.go`
Add commands to it by running `cobra add [cmdname]`
这个命令会帮你生成这样一个框架代码
maojun@maojun-mbp$ tree demo
demo
├── LICENSE
├── cmd
│ └── root.go
└── main.go
简单的CLI
在写一些简单的CLI的时候我们其实是不需要有子命令的,我们往往需要这样一种简单的CLI
demo.exe
Demo is a test appcation for print things
Usage:
demo [flags]
Flags:
-a, --age int person's age
-h, --help help for demo
-n, --name string person's name
接下来我们就在上面生成的代码的基础上完成一个不带子命令的CLI。首先,我需要编写我的业务逻辑,因此我在demo下面新建一个包,名称为simple。如下:
maojun@maojun-mbp$ tree .
.
├── LICENSE
├── cmd
│ └── root.go
├── main.go
└── simple
├── simple.go
└── simple_test.go
这里仅仅实现一个print作为样例,因此simple.go是这样实现的
package simple
import (
"fmt"
)
func Show(name string, age int) {
fmt.Printf("My name is %s, my age is %d\n", name, age)
}
接下来我们需要将我们实行的整个Show方法暴露给CLI, 我们从生成的main文件入手分析。
- 在main里面调用了 demo/cmd包里面暴露的Execute 函数 [cmd.Execute()]
- 在demo/cmd/root.go中发现Execute执行的是RootCmd.Execute()
- 而RootCmd是一个cobra的Command结构体[RootCmd = &cobra.Command]
显然我们想要实行不带子命令的CLI,只需要将RootCmd的修改成我们需要的结构体就ok了
这里做了几点修改
- RootCmd中的Command结构体中的Run方法需要我们定义, 主要功能就是调用simple里面的Show接口
- cmd包初始化得时候需要通过RootCmd.Flags()获取命令行传入的name和age的参数,因此这里需要修改init方法
- 最后我们不需要从配置文件读取配置,注释掉:nitConfig函数和”http://github.com/spf13/viper”
最终这个root.go是这样的
最后测试下是不是我们想要的效果
maojun@maojun-mbp$ go run main.go -h
Demo is a test appcation for print things
Usage:
demo [flags]
Flags:
-a, --age int person's age
-n, --name string persion's name
maojun@maojun-mbp$ go run main.go -n "test" -a 10
My name is test, my age is 10
带子命令的CLI
对于复杂的情况,往往需要带子命令场景,比如Docker的CLI,而最终的效果应该是这样的
demo
Demo is a test appcation for print things
Usage:
demo [flags]
demo [command]
Available Commands:
test A brief description of your command
Flags:
-a, --age int person's age
-h, --help help for demo
-n, --name string person's name
Use "demo [command] --help" for more information about a command.
支持子命令是cobra的自己的功能,因此直接可以通过cobra生成带子命令的代码
maojun@maojun-mbp$ cobra init demo
Your Cobra application is ready at
/Users/maojun/GoWorkDir/src/demo
Give it a try by going there and running `go run main.go`
Add commands to it by running `cobra add [cmdname]`
maojun@maojun-mbp$ cobra add test
test created at /Users/maojun/GoWorkDir/src/cmd/test.go
注释掉root.go那些不需要的地方, 然后修改生成的test.go
最后测试下是不是我们想要的效果
maojun@maojun-mbp$ go run main.go -h
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.
Usage:
demo [command]
Available Commands:
test A brief description of your command
Flags:
--config string config file (default is $HOME/.demo.yaml)
-t, --toggle Help message for toggle
Use "demo [command] --help" for more information about a command.
maojun@maojun-mbp$ go run main.go test -h
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.
Usage:
demo test [flags]
Flags:
-a, --age int person's age
-n, --name string persion's name
Global Flags:
--config string config file (default is $HOME/.demo.yaml)
maojun@maojun-mbp$ go run main.go test -a 10 -n test
My name is test, my age is 10
命令行补全,man这些可以自己手动测试。