Golang : cobra 包简介

2019年7月2日10:57:54Golang : cobra 包简介已关闭评论 269

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

Golang : cobra 包简介

主要功用

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

Golang : cobra 包简介

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

Golang : cobra 包简介

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

Golang : cobra 包简介

运用 cobra 递次天生敕令代码

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

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

Golang : cobra 包简介

这两条敕令离别天生了 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 要领:

Golang : cobra 包简介

再建立一个 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")
    },
}

Golang : cobra 包简介

为 Command 增加选项(flags)

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

  • persistent
  • local

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

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

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

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

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

var Name string
rootCmd.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

Golang : cobra 包简介

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

Golang : cobra 包简介

资助信息(help command)

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

Golang : cobra 包简介

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

$ cobrademo help image

Golang : cobra 包简介

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

$ cobrademo help image times

Golang : cobra 包简介

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

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

提醒信息(usage message)

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

Golang : cobra 包简介

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

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 递次并实行,输出效果中能够看到这些要领的实行递次:

Golang : cobra 包简介

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

Golang : cobra 包简介

对未知敕令的提醒

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

Golang : cobra 包简介

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

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

总结

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

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

avatar