Go语言cobra库学习笔记——从入门到精通

Go语言中,我们可以使用cobra很方便的进行命令行工具的开发,kubelet命令就是使用这个库开发的。在这片博客中,我将会总结一下我学习cobra库的笔记,希望对你有帮助。点击这里可以进入cobra官方说明。

一、安装cobra

1. 安装cobra

go get github.com/spf13/cobra/cobra
将cobra下载完成后,GOPATH/bin目录会生成一个cobra可执行程序,通过这个程序我们可以初始化一个cobra代码框架。

2. 初始化一个项目

我们可以通过下面的命令初始化项目:
mkdir -p newApp && cd newApp
cobra init --pkg-name github.com/spf13/newApp
或者
cobra init --pkg-name github.com/spf13/newApp path/to/newApp

上面是官方的示例,需要注意的是–pkg-name后面接的是你要编写的命令的名称,不一定是你新建目录的名称。
这里我举个例子,初始化一个time命令:

$ cobra init --pkg-name time
Your Cobra applicaton is ready at
D:\GOCODE\cobraStudy

初始化之后可以看到,cobra命令在项目目录底下创建了开发框架:
Go语言cobra库学习笔记——从入门到精通_第1张图片
root.go代码中有一个rootCmd变量:

  • Use: 命令。
  • Short: 命令的简短描述。
  • Long: 命令的详细描述,在帮助命令,如$ [appName] -h或者$ [appName] [command] -h时会显示此程序和此命令的字符串。
  • Run: 命令执行入口,函数主要写在这个模块中。

函数initConfig(): 用来初始化viper配置文件位置,监听变化。
函数init(): 定义flag和配置处理。

我们可以编译一下:
$ go build -o time main.go
然后执行time命令:

$ ./time
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.

因为我们开没有进行开发,因此我们可以看到当前time命令只有一些帮助信息。

3.通过cobra命令添加命令

添加命令之前我们需要理解cobra的三个概念:

  • commands
  • arguments
  • flags

其中commands代表行为,arguments代表数值,flags代表对行为的改变。
执行命令行程序时的一般格式为:
[appName] [command] [arguments] --[flag]
这里我们在上面创建的项目基础上添加命令:

$ cobra add show
show created at D:\GOCODE\cobraStudy

此时,cmd目录会多一个show.go的文件,我们可以在这个文件中定义show具体执行的操作,这里的show就是上面说的command。
我们现在编译一下代码:

$ go build -o time main.go

执行命令,我们可以看到time命令的帮助信息,在usage中我们可以看到,当前有两个command一个是默认的help另一个就是我们刚才创建的show,Flags也有两个,这是初始化的时候自带的,后面我们可以自己进行修改。

$ ./time
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:
  time [command]

Available Commands:
  help        Help about any command
  show        A brief description of your command

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

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

4.为 Command 添加选项(flags)

选项(flags)用来控制 Command 的具体行为。根据选项的作用范围,可以把选项分为两类:

  • persistent
  • local

1)对于 persistent 类型的选项,既可以设置给该 Command,又可以设置给该 Command 的子 Command。对于一些全局性的选项,比较适合设置为 persistent 类型,比如控制输出的 verbose 选项:
我们创建一个test命令:

$ cobra add test
test created at D:\GOCODE\cobraStudy

在test.go文件的init()函数中我们可以通过下面的方式给test命令添加flags:

	// 下面定义了一个Flag foo, foo后面接的值会被赋值给Foo
	Foo = testCmd.PersistentFlags().String("foo", "", "A help for foo")
	// 下面定义了一个Flag print ,print后面的值会被赋值给Print变量
	testCmd.PersistentFlags().StringVar(&Print, "print", "", "print")
	// 下面定义了一个Flag show,show默认为false, 有两种调用方式--show\-s,命令后面接了show则上面定义的show变量就会变成true
	testCmd.PersistentFlags().BoolVarP(&show, "show", "s", false, "show")

需要注意的是,上例中我创建的Foo、Print、show都是全局变量,如果没有创建,代码会执行不成功。
上面是常见的定义方式,更多定义方式请参考原码。
我们修改一下Run后面的函数:

Run: func(cmd *cobra.Command, args []string) {
		if show {
			fmt.Println("Show")
		}
		fmt.Println("Print:", Print)
		fmt.Println("Foo:", *Foo)
	},

编译后执行命令:

$ ./time test --foo hello -s --print world
Show
Print: world
Foo: hello

2)local 类型的选项只能设置给指定的 Command:

// 下面定义了一个Flag show,show默认为false, 有两种调用方式--show\-s,命令后面接了show则上面定义的show变量就会变成true
	showL = *testCmd.Flags().BoolP("showL", "S", false, "show")
	// 下面定义了一个Flag print ,print后面的值会被赋值给Print变量
	testCmd.Flags().StringVar(&PrintL, "printL", "", "print")
	// 下面定义了一个Flag foo, foo后面接的值会被赋值给Foo
	FooL = testCmd.Flags().String("fooL", "", "A help for foo")

默认情况下的选项都是可选的,但一些用例要求用户必须设置某些选项,这种情况 cobra 也是支持的,通过 Command 的 MarkFlagRequired 方法标记该选项即可:

show = *testCmd.Flags().BoolP("show", "s", false, "show")
// 设置使用test的时候后面必须接show
_ = testCmd.MarkFlagRequired("show")

5.命令行参数(arguments)

首先我们来搞清楚命令行参数(arguments)与命令行选项(flags/options)的区别。以常见的 ls 命令来说,其命令行的格式为:

$ ls --help
Usage: 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 至少有一个位置参数,可以这样初始化它:

// testCmd represents the test command
var testCmd = &cobra.Command{
	Use: "test",
	// 定义arguments数量最少为1个
	Args:  cobra.MinimumNArgs(1),
	Short: "short usage",
	Long:  `Long usage`,
	Run: func(cmd *cobra.Command, args []string) {
		if show {
			fmt.Println("Show")
			fmt.Println("Print:", Print)
			fmt.Println("Foo:", *Foo)
		}
	},
}

二、使用cobra开发一个命令

1. 这里我们以一个time命令为例,讲解如何使用cobra开发一个命令

功能功能说明:
(1)show 查看当前时间
(2)parse 指定时间格式 --format,parse为show的子命令。

2.实现show命令

在第一部分我们已经添加了show命令,现在我们修改show.go文件。
1)首先我们实现输出当前时间的功能。
下面是初始化的内容:

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

命令实现的功能由Command.Run控制,我们定义一个函数,输出当前时间:

// ShowTime 显示当前时间
func ShowTime(cmd *cobra.Command, args []string) {
	fmt.Println(time.Now())
}

然后将函数给Command.Run赋值:

// showCmd represents the show command
var showCmd = &cobra.Command{
	Use:   "show",
	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: ShowTime, // 这里改为函数名称
}

2)修改help命令。
help命令有两个,一个是short一个是lang,很明显short命令用来定义简短的说明,lang命令用来定义详细说明,下面我们修改show命令的help:

// showCmd represents the show command
var showCmd = &cobra.Command{
	Use:   "show",
	Short: "Displays the current time",
	Long: `You can use the time show command to view the current time. For example:

$ ./time show
2020-07-03 15:01:59.6035666 +0800 CST m=+0.013998501`,
	Run: ShowTime,
}

修改完成,我们编译代码:

$ go build -o time main.go

执行time命令,我们可以看到show命令后面的说明变成了我们定义的简短说明:

$ ./time
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:
  time [command]

Available Commands:
  help        Help about any command
  show        Displays the current time

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

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

我们再执行time show --help命令,可以看到现在展示了show命令的详细说明:

$ ./time show --help
You can use the time show command to view the current time. For example:

$ ./time show
2020-07-03 15:01:59.6035666 +0800 CST m=+0.013998501

Usage:
  time show [flags]

Flags:
  -h, --help   help for show

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

3.实现parse命令

1)添加parse命令
下面的命令通过-p指定parse为show的子命令,注意命令后面接Cmd

$ cobra add parse -p showCmd
parse created at D:\GOCODE\cobraStudy

2)编辑parse命令

// parseCmd represents the parse command
var parseCmd = &cobra.Command{
	Use:   "parse",
	Short: "Format current time",
	Long: `Format current time. For example:

time show parse --format "2006:01:02 15:04:05".`,
	Run: func(cmd *cobra.Command, args []string) {
		// 输出格式化之后的时间
		fmt.Println(time.Now().Format(format))
	},
}
var format string

func init() {
	showCmd.AddCommand(parseCmd)
	parseCmd.Flags().StringVarP(&format, "format", "f", "", "Help message for toggle")
	// 这里指定format flag为必须
	_ = parseCmd.MarkFlagRequired("format")
}

编译命令并执行:

$ ./time show parse --format="2006:01:02 15:04:05"
2020:07:03 17:04:05

4.修改time命令的配置信息

修改root.go文件,删除没有用的代码:

// rootCmd represents the base command when called without any subcommands
var rootCmd = &cobra.Command{
	Use:   "time",
	Short: "Show Current Time",
	Long: `Show Current Time. For example:

With this command, you can view the current time or customize the time format.`,
}
func init() {
	cobra.OnInitialize(initConfig)
}

测试一下命令:

random@random-wz MINGW64 /d/GOCODE/cobraStudy
$ ./time --help
Show Current Time. For example:

With this command, you can view the current time or customize the time format.

Usage:
  time [command]

Available Commands:
  help        Help about any command
  show        Displays the current time

Flags:
  -h, --help   help for time

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

random@random-wz MINGW64 /d/GOCODE/cobraStudy
$ ./time show
2020-07-03 17:10:04.8230742 +0800 CST m=+0.014971101

random@random-wz MINGW64 /d/GOCODE/cobraStudy
$ ./time show parse
Error: required flag(s) "format" not set
Usage:
  time show parse [flags]

Flags:
  -f, --format string   Help message for toggle
  -h, --help            help for parse

required flag(s) "format" not set

random@random-wz MINGW64 /d/GOCODE/cobraStudy
$ ./time show parse -f "15:04:05"
17:10:25

你可能感兴趣的:(#,Go语言进阶,cobra,FlagRequired,Persistent,Local,cobra,init)