cobra

cobra 是go的cli框架,包含cli库和生成基于cobra cli应用的命令行工具

简介

  • 子命令,如app serverapp sub
  • 完整兼容POSIX的flag,包括长命名和短命名
  • 子命令的嵌套(子命令)
  • 全局、本地、级联三种flag
  • 好用的工具命令,如cobra init appname初始化cli程序,cobra add cmdname为cli程序增加子命令
  • 智能提示
  • 生成命令help,以及为每个flag、cmd生成-h--help帮助
  • 生成自动补全功能
  • 生成man帮助文档
  • 命令别名
  • 自定义帮助、用法
  • 为达到saas的12-factor 可选择viper

安装

go get -u github.com/spf13/cobra/cobra会自动安装最新版本库和命令行工具,国内下不下来可以手动下载放到对应的文件夹中,然后就可以在你的code里应用它import "github.com/spf13/cobra"

概念

cobra主要管理commands、args、flags,commands代表一个命令或动作,一般用动词命名,args代表输入的参数,一般用名词命名,flags是对commands的修饰,一般用形容词命名;好的cli应用应该学习成本低,用户容易理解 cli的含义,git的例子能很好的说明这一点: git clone URL --bare ,clone是commands是动词,URL是args是你的输入,bare是flag是形容词

commands

commands是cli应用的核心,每次交互都包含在一个command中,command可以拥有可选的子命令(sub commands)

flags

flag 是修饰command的一种方式,cobra支持完全兼容的POSIX flag以及go的 flag包,一个flag可以被定义成仅对当前命令生效或对当前及子孙命令生效(对于写代码时增加flag来说),flag功能由pflag library提供

开始使用

虽然你可以自定义你自己的应用工程结构,但推荐你使用以下cobra-cli应用的典型结构

1
2
3
4
5
6
7
▾ appName/
▾ cmd/
add.go
your.go
commands.go
here.go
main.go

在cobra应用中,main.go通常只提供初始化cobra的功能,like that

1
2
3
4
5
6
7
8
9
package main

import (
"{pathToYourApp}/cmd"
)

func main() {
cmd.Execute()
}

使用cobra生成工具

cobra提供了帮你生成模板的cli工具,有如下命令:

初始化应用init

cobra init [name] [flags],name是你cobra应用的名字,--pkg-namepkg 的名字 flag可以选择-a 作者名,-l添加license,默认Apache2.0,--viper添加viper等功能,具体如下

1
2
3
4
5
--pkg-name string   fully qualified pkg name
-a, --author string author name for copyright attribution (default "YOUR NAME")
--config string config file (default is $HOME/.cobra.yaml)
-l, --license string name of license for the project
--viper use Viper for configuration (default true)

初始化应用后一般go mod init初始化应用,golang基础,在此不赘述

添加commands

cobra add [name] -p 'parentComand' -p可以为特定命令添加子命令,缺省为根命令

使用Cobra库

手动创建需要新建一个rootCmd文件,然后添加若干command

创建rootCmd

cobra不需要创建一个特定的实例,可以直接使用&cobra.Commaand,如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
var rootCmd = &cobra.Command{
Use: "hugo", //command,代表命令
Short: "Hugo is a very fast static site generator", //对command的简短介绍
Long: `A Fast and Flexible Static Site Generator built with
love by spf13 and friends in Go.
Complete documentation is available at http://hugo.spf13.com`, //对command的详细介绍
Run: func(cmd *cobra.Command, args []string) {
// 命令实际要做的事情
},
}
func Execute() { //启动
if err := rootCmd.Execute(); err != nil {
fmt.Println(err)
os.Exit(1)
}
}

你可以在init中定义flatgs以及处理配置,示例如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
import (
"fmt"
"os"
homedir "github.com/mitchellh/go-homedir"
"github.com/spf13/cobra"
"github.com/spf13/viper"
)
func init() {
cobra.OnInitialize(initConfig) //初始化配置
rootCmd.PersistentFlags().StringVar(&cfgFile, "config", "", "config file (default is $HOME/.cobra.yaml)")//配置
rootCmd.PersistentFlags().StringVarP(&projectBase, "projectbase", "b", "", "base project directory eg. github.com/spf13/")
rootCmd.PersistentFlags().StringP("author", "a", "YOUR NAME", "Author name for copyright attribution")
rootCmd.PersistentFlags().StringVarP(&userLicense, "license", "l", "", "Name of license for the project (can provide `licensetext` in config)")
rootCmd.PersistentFlags().Bool("viper", true, "Use Viper for configuration")
viper.BindPFlag("author", rootCmd.PersistentFlags().Lookup("author"))//绑定viper的标致到cobra
viper.BindPFlag("projectbase", rootCmd.PersistentFlags().Lookup("projectbase"))
viper.BindPFlag("useViper", rootCmd.PersistentFlags().Lookup("viper"))
viper.SetDefault("author", "NAME HERE <EMAIL ADDRESS>")
viper.SetDefault("license", "apache")
}
func initConfig() {
// viper读取配置文件
if cfgFile != "" {
// 从flag读取文件
viper.SetConfigFile(cfgFile)
} else {
// 获取主目录
home, err := homedir.Dir()
if err != nil {
fmt.Println(err)
os.Exit(1)
}
// 查找文件.cobra
viper.AddConfigPath(home)
viper.SetConfigName(".cobra")
}
if err := viper.ReadInConfig(); err != nil {
fmt.Println("Can't read config:", err)
os.Exit(1)
}
}

添加命令

添加的命令可以创建在cmd目录下单独的go文件,比如创建一个version命令:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
package cmd

import (
"fmt"

"github.com/spf13/cobra"
)

func init() {
rootCmd.AddCommand(versionCmd)
}

var versionCmd = &cobra.Command{
Use: "version",
Short: "Print the version number of Hugo",
Long: `All software has versions. This is Hugo's`,
Run: func(cmd *cobra.Command, args []string) {
fmt.Println("Hugo Static Site Generator v0.9 -- HEAD")
},
}

使用flag

我们有两种

使用步骤

环境准备

  1. go mod init yourpackage 创建你自己的模块
  2. go get -u github.com/spf13/cobra/cobra 加载依赖

初始化

  1. cobra init ./ -a longtao -l GPL --viper 初始化包(在当前目录初始化cobra,作者是longtao,许可是gpl,并使用viper配置)
  2. go build -o ./ . 编译测试一下是否正常使用