Cobra 是一个 Golang 包,它供应了简朴的接口来建立敕令行递次。同时,Cobra 也是一个运用递次,用来天生运用框架,从而开辟以 Cobra 为基础的运用。本文的演示状况为 ubuntu 18.04(下图来自互联网)。

主要功用

cobra 的主要功用以下,能够说每一项都很有用:

  • 浅易的子敕令行情势,如 app server, app fetch 等等
  • 完全兼容 posix 敕令行情势
  • 嵌套子敕令 subcommand
  • 支撑全局,部分,串连 flags
  • 运用 cobra 很轻易的天生运用递次和敕令,运用 cobra create appname 和 cobra add cmdname
  • 若是敕令输入毛病,将供应智能发起,如 app srver,将提醒 srver 没有,是否是 app server
  • 自动天生 commands 和 flags 的资助信息
  • 自动天生细致的 help 信息,如 app help
  • 自动识别资助 flag -h,--help
  • 自动天生运用递次在 bash 下敕令自动完成功用
  • 自动天生运用递次的 man 手册
  • 敕令行别号
  • 自界说 help 和 usage 信息
  • 可选的与 viper apps 的严密集成

cobra 中的主要观点

cobra 中有个主要的观点,离别是 commands、arguments 和 flags。个中 commands 代表行动,arguments 就是敕令行参数(或许称为地位参数),flags 代表对行动的转变(也就是我们常说的敕令行选项)。实行敕令行递次时的一样平常花样为:
APPNAME COMMAND ARG --FLAG
比以下面的例子:

# server是 commands,port 是 flag
hugo server
--port=1313# clone 是 commands,URL 是 arguments,brae 是 flag
git clone URL
--bare

若是是一个简朴的递次(功用单一的递次),运用 commands 的体式格局可能会很烦琐,然则像 git、docker 等运用,把这些本就很庞杂的功用划分为子敕令的情势,会方便运用(对递次的设计者来讲又未尝不是云云)。

建立 cobra 运用

在建立 cobra 运用前须要先装置 cobra 包:

$ go get -u github.com/spf13/cobra/cobra

然后就能够用 cobra 递次天生运用递次框架了:

$ cobra init appname

若是不想让运用递次在默许的目次下,就要指定运用递次地点的相对目次,好比 ~/go/src/godemos/cobrademo,天生的文件以下:

此时的递次并没有甚么功用,实行它只会输出一些默许的提醒信息:

运用 cobra 递次天生敕令代码

除天生运用递次框架,还能够经由历程 cobra add 敕令天生子敕令的代码文件,比以下面的敕令会增加两个子敕令 image 和 container 相干的代码文件:

$ cd ~/go/src/godemos/cobrademo
$ cobra add image
$ cobra add container

这两条敕令离别天生了 cobrademo 递次中 image 和 container 子敕令的代码,固然了,详细的功用还得靠我们本身完成。

为敕令增加详细的功用

到目前为止,我们一共为 cobrademo 递次增加了三个 Command,离别是 rootCmd(cobra init 敕令默许天生)、imageCmd 和 containerCmd。
翻开文件 root.go ,找到变量 rootCmd 的初始化历程并为之设置 Run 要领:

Run: func(cmd *cobra.Command, args []string) {
fmt.Println(
"cobra demo program")
},

从新编译 cobrademo 递次并不带参数运转,此次就不再输出资助信息了,而是实行了 rootCmd 的 Run 要领:

再建立一个 version Command 用来输出以后的软件版本。先在 cmd 目次下增加 version.go 文件,编纂文件的内容以下:

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 cobrademo",
Long: `All software has versions. This
is cobrademo's`, Run: func(cmd *cobra.Command, args []string) {
fmt.Println(
"cobrademo version is v1.0")
},
}

为 Command 增加选项(flags)

选项(flags)用来掌握 Command 的详细行动。依据选项的作用局限,能够把选项分为两类:

  • persistent
  • local

关于 persistent 范例的选项,既能够设置给该 Command,又能够设置给该 Command 的子 Command。关于一些全局性的选项,对照合适设置为 persistent 范例,好比掌握输出的 verbose 选项:

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

local 范例的选项只能设置给指定的 Command,比以下面界说的 source 选项:

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

该选项不克不及指定给 rootCmd 以外的别的 Command。
默许状况下的选项都是可选的,但一些用例请求用户必需设置某些选项,这类状况 cobra 也是支撑的,经由历程 Command 的 MarkFlagRequired 要领符号该选项便可:

var Name stringrootCmd.Flags().StringVarP(&Name, "name", "n", "", "user name (required)")
rootCmd.MarkFlagRequired(
"name")

敕令行参数(arguments)

起首我们来搞清晰敕令行参数(arguments)与敕令行选项的区分(flags/options)。以罕见的 ls 敕令来讲,其敕令行的花样为:
ls [OPTION]... [FILE]…
个中的 OPTION 对应本文中引见的 flags,以 - 或 -- 开首;而 FILE 则被称为参数(arguments)或地位参数。一样平常的规则是参数在所有选项的背面,上面的 … 透露表现能够指定多个选项和多个参数。

cobra 默许供应了一些考证要领:

  • NoArgs - 若是存在任何地位参数,该敕令将报错
  • ArbitraryArgs - 该敕令会接收任何地位参数
  • OnlyValidArgs - 若是有任何地位参数不在敕令的 ValidArgs 字段中,该敕令将报错
  • MinimumNArgs(int) - 最少要有 N 个地位参数,否则报错
  • MaximumNArgs(int) - 若是地位参数凌驾 N 个将报错
  • ExactArgs(int) - 必需有 N 个地位参数,否则报错
  • ExactValidArgs(int) 必需有 N 个地位参数,且都在敕令的 ValidArgs 字段中,否则报错
  • RangeArgs(min, max) - 若是地位参数的个数不在区间 min 和 max 当中,报错

好比要让 Command cmdTimes 最少有一个地位参数,能够如许初始化它:

var cmdTimes = &cobra.Command{
Use: …
Short: …
Long: …
Args: cobra.MinimumNArgs(
1),
Run: …
}

一个完全的 demo

我们在前面建立的代码的基础上,为 image 敕令增加行动(打印信息到掌握台),并为它增加一个子敕令 cmdTimes,下面是更新后的 image.go 文件的内容(本文 demo 的完全代码请参考这里):

package cmd

import (
"fmt" "github.com/spf13/cobra" "strings")//imageCmd represents the image command var imageCmd = &cobra.Command{
Use:
"image",
Short:
"Print images information",
Long:
"Print all images information",
Run: func(cmd
*cobra.Command, args []string) {
fmt.Println(
"image one is ubuntu 16.04")
fmt.Println(
"image two is ubuntu 18.04")
fmt.Println(
"image args are :" + strings.Join(args, " "))
},
}
var echoTimes int var cmdTimes = &cobra.Command{
Use:
"times [string to echo]",
Short:
"Echo anything to the screen more times",
Long: `echo things multiple times back to the user by providing
a count and a
string.`,
Args: cobra.MinimumNArgs(
1),
Run: func(cmd
*cobra.Command, args []string) {for i := 0; i < echoTimes; i++{
fmt.Println(
"Echo:" + strings.Join(args, " "))
}
},
}

func init() {
rootCmd.AddCommand(imageCmd)
cmdTimes.Flags().IntVarP(
&echoTimes, "times", "t", 1, "times to echo the input")
imageCmd.AddCommand(cmdTimes)
}

编译后实行敕令:

$ ./cobrademo image hello
$ .
/cobrademo image times -t=3 world

由于我们为 cmdTimes 敕令设置了 Args: cobra.MinimumNArgs(1),以是必需为 times 子敕令传入一个参数,否则 times 子敕令会报错:

资助信息(help command)

cobra 会自动增加 --help(-h)选项,以是我们能够没必要增加该选项而直接运用:

cobra 同时还自动增加了 help 子命,默许效果和运用 --help 选项雷同。若是为 help 敕令通报别的敕令作为参数,则会显现对应敕令的资助信息,下面的敕令输出 image 子敕令的资助信息:

$ cobrademo help image

固然也能够经由历程这类体式格局检察子敕令的子敕令的资助文档:

$ cobrademo help image times

除 cobra 默许的资助敕令,我们还能够经由历程下面的体式格局举行自界说:

cmd.SetHelpCommand(cmd *Command)
cmd.SetHelpFunc(f func(
*Command, []string))
cmd.SetHelpTemplate(s
string)

提醒信息(usage message)

提醒信息和资助信息很类似,只不过它是在你输入了不法的参数、选项或敕令时才涌现的:

和资助信息一样,我们也能够经由历程下面的体式格局自界说提醒信息:

cmd.SetUsageFunc(f func(*Command) error)
cmd.SetUsageTemplate(s
string)

在 Commnad 实行前后实行分外的操纵

Command 实行的操纵是经由历程 Command.Run 要领完成的,为了支撑我们在 Run 要领实行的前后实行一些别的的操纵,Command 还供应了分外的几个要领,它们的实行递次以下:
    1. PersistentPreRun
    2. PreRun
    3. Run
    4. PostRun
    5. PersistentPostRun
修正 rootCmd 的初始化代码以下:

var rootCmd = &cobra.Command{
Use:
"cobrademo",
Short:
"sparkdev's cobra demo",
Long:
"the demo show how to use cobra package",
PersistentPreRun: func(cmd
*cobra.Command, args []string) {
fmt.Printf(
"Inside rootCmd PersistentPreRun with args: %v\n", args)
},
PreRun: func(cmd
*cobra.Command, args []string) {
fmt.Printf(
"Inside rootCmd PreRun with args: %v\n", args)
},
Run: func(cmd
*cobra.Command, args []string) {
fmt.Printf(
"cobra demo program, with args: %v\n", args)
},
PostRun: func(cmd
*cobra.Command, args []string) {
fmt.Printf(
"Inside rootCmd PostRun with args: %v\n", args)
},
PersistentPostRun: func(cmd
*cobra.Command, args []string) {
fmt.Printf(
"Inside rootCmd PersistentPostRun with args: %v\n", args)
},
}

从新编译 cobrademo 递次并实行,输出效果中能够看到这些要领的实行递次:

个中的 PersistentPreRun 要领和 PersistentPostRun 要领会随同任何子敕令的实行:

对未知敕令的提醒

若是我们输入了不正确的敕令或许是选项,cobra 还会只能的给出提醒:

上图的敕令我们只输入了子敕令 image 的前两个字母,然则 cobra 已能够给出很细致的提醒了。关于如许的提醒我们也是能够自界说的,或许若是觉着没用就直接封闭掉。

本文 demo 的完全代码请参考这里。

总结

cobra 是一个异常有用(盛行)的包,许多优异的开源运用都在运用它,包罗 Docker 和 Kubernetes 等等。当我们熟习了 cobra 包的基础用法后,再去看 Docker 等运用的敕令行东西的花样,是否是就很轻易理解了!

参考:
spf13/cobra
Golang之运用Cobra
MAKE YOUR OWN CLI WITH GOLANG AND COBRA
Cobra简介
golang敕令行库cobra的运用

Last modification:March 25, 2020
如果觉得我的文章对你有用,请随意赞赏