Cobra Command 详解
在完成上面的例子之后,我们来仔细看下 cobra.Command 的定义,基本上所有命令相关的功能都定义在这个结构体里面了,我们忽略一些没有导出的成员,备注:因为西部数码的虚拟主机太垃圾,好多文字写进去被拦截了,有些地方中间加了空格。
type Command struct {
// Use 表示用一句话来描述这个命令作用,这段话的第一个单词会被作为这个命令的名称
// 这个设置在子命令中生效,对于根命令则没有意义
Use string
// Alias 可以用来给子命令定义别名,除了使用 Use 中的第一个单词作为子命令外,你还可以使用这个 Alias
// 里面定义的任何一个名称作为子命令名称
Aliases []string
// SuggestFor 定义一组提示命令,当输入匹配其中任何一个命令的时候,会提示是否希望输入的为 echo 命令
SuggestFor []string
// Short 是用来在帮助信息位置显示的简短命令帮助
Short string
// Long 是用来在使用命令 'help ' 显示帮助信息时显示的长文字
Long string
// Example 用来定义子命令使用的具体示例,可以在里面定义多行不同的命令使用样例,供用户参考,这一点在
// Kubectl 命令中体现的非常明显,因为 Kubectl 命令很复杂,参数也很多,所有样例会极大方便用户
Example string
// ValidArgs 是一组可用在 Bash 补全中的合法的非选项参数
ValidArgs []string
// Args 表示期望的参数
Args PositionalArgs
// ArgAliases 是 ValidArgs 的一组别名
// 这些参数不会在 Bash 补全中提示给用户,但是如果手动输入的话,也是允许的
ArgAliases []string
// BashCompletionFunction 是 Bash 自动补全生成器使用的自定义函数
BashCompletionFunction string
// Deprecated 不为空的时候,在命令执行时都会提示命令已废弃,并且输出这段文字
Deprecated string
// Hidden 参数设置为 true 的时候,将无法在命令帮助列表中看到这个命令,但是实际这个命令仍然是可用的,一般用于
// 对命令做向下兼容的处理,在未来的版本中如果这个命令会废弃,那么先让它隐藏起来会比直接删除较好
Hidden bool
// Annotations 定义一些键值对,应用可以用这些注解来分组命令,主要用于标注上面的分组
Annotations map[string]string
// Version 定义这个命令的版本。当 Version 值不为空,且命令没有定义 version 选项的时候,会自动给这个命令增加一个
// boolean 类型,名称为 version 的选项。如果指定这个选项,就会输出这里 Version 的值。
Version string
// 下面的这组 Run 函数执行顺序为:
// * PersistentPreRun()
// * PreRun()
// * Run()
// * PostRun()
// * PersistentPostRun()
// 所有的函数传入的参数都相同,都是命令名称之后的参数
// PersistentPreRun 这个命令的子命令都将继承并执行这个函数
PersistentPreRun func(cmd *Command, args []string)
// PersistentPreRunE 和 PersistentPreRun 一样,但是遇到错误时可以返回一个错误
// 一旦这个函数返回的 error 不为 nil,那么执行就中断了。所以你可以在这个函数里面
// 做诸如权限验证等等全局性的工作
PersistentPreRunE func(cmd *Command, args []string) error
// PreRun 这个命令的子命令不会继承和运行这个函数
PreRun func(cmd *Command, args []string)
// PreRunE 和 PreRun 一样,但是遇到错误时可以返回一个错误
// 一旦这个函数返回的 error 不为 nil,那么执行就中断了。所以你可以在这个函数里面
// 做一些和该命令相关的输入参数检测之类的工作
PreRunE func(cmd *Command, args []string) error
// Run 命令核心工作所在的函数,大多数情况下只实现这个命令即可
Run func(cmd *Command, args []string)
// RunE 和 Run 一样,但是遇到错误时可以返回一个错误
// 一旦这个函数返回的 error 不为 nil,那么执行就中断了。
RunE func(cmd *Command, args []string) error
// PostRun 在 Run 函数执行之后执行
PostRun func(cmd *Command, args []string)
// PostRunE 在 PostRun 之后执行,但是可以返回一个错误
// 一旦这个函数返回的 error 不为 nil,那么执行就中断了。
PostRunE func(cmd *Command, args []string) error
// PersistentPostRun 在 PostRun 之后执行,这个命令的子命令都将继承并执行这个函数
PersistentPostRun func(cmd *Command, args []string)
// PersistentPostRunE 和 PersistentPostRun 一样,但是可以返回一个错误
// 一旦这个函数返回的 error 不为 nil,那么执行就中断了。
PersistentPostRunE func(cmd *Command, args []string) error
// SilenceErrors 设置为 true 时可以在命令执行过程中遇到任何错误时,不显示错误
SilenceErrors bool
// SilenceUsage 设置为 true 时可以在命令执行遇到输入错误时,不显示使用方法
SilenceUsage bool
// DisableFlagParsing 设置为 true 时将禁用选项解析功能,这样命令之后所有的内容
// 都将作为参数传递给命令
DisableFlagParsing bool
// DisableAutoGenTag 在生成命令文档的时候是否显示 gen tag
DisableAutoGenTag bool
// DisableFlagsInUseLine 设置为 true 的时候,将不会在命令帮助信息或者文档中显示命令支持的选项
DisableFlagsInUseLine bool
// DisableSuggestions 禁用命令提示
DisableSuggestions bool
// SuggestionsMinimumDistance 定义显示命令提示的最小的 Levenshtein 距离
SuggestionsMinimumDistance int
// TraverseChildren 在执行该命令子命令前,解析所有父命令的选项
TraverseChildren bool
//FParseErrWhitelist 定义可以被忽略的解析错误
FParseErrWhitelist FParseErrWhitelist
}
我们可以结合上面对 cobra.Command 的讲解,自行调整各个参数的值来实际体验下它的工作方式。这里提供一个代码模板,大家可以修改这个代码并执行实践一下。
在/home/yinzhong目录下新建cobra-echo-more.go文件并写入如下代码:
// /home/yinzhong/cobra-echo-more.go
package main
import (
"fmt"
"strings"
"github.com/spf13/cobra"
)
func main() {
rootCmd := cobra.Command{
// 我们定义这个工具默认输出帮助信息
Run: func(cmd *cobra.Command, args []string) {
cmd.Help()
},
}
// 定义一个子命令,直接输出命令行参数
echoCmd := cobra.Command{
// 子命令描述,第一个单词作为子命令名称
Use: "echo inputs",
// 子命令别名,可以使用任何一个别名替代上面的 echo 来运行子命令
Aliases: []string{
"copy",
"repeat",
},
// 命令提示,默认情况如果输入的子命令不存在会提示 unknown cmd,
// 但是如果定义了 SuggestFor 的情况下,如果输入的命令不存在,会去 SuggestFor
// 里面查找是否有匹配的字符串,如果有,则提示是否期望输入的是 echo 命令
SuggestFor: []string{
"ech", "cp", "rp",
},
DisableSuggestions: true,
SuggestionsMinimumDistance: 2,
DisableFlagsInUseLine: true,
// 简单扼要概括下命令的用途
Short: "echo is a command to echo command line inputs",
// 想说什么都在这里说吧,越详细越好,可以使用 `` 来跨行输入
Long: `echo is a command to echo command line inputs.
It is a very simple command used to display how to implement command line tools
using cobra, which is a very famous library to build command line interface tools.
`,
// 当你在新版本废弃这个命令的时候,可以先隐藏,让用户优先使用替代品或者看不到,
// 但是处于向下兼容目的,这个命令仍然是可用的,只是在帮助列表里面看不到
//Hidden: true,
// 当你需要废弃这个命令的时候设置。废弃的意思意味着未来版本可能删除这个命令。
// 标注为废弃的命令在执行的时候,都会打印命令已废弃的提示信息以及这个设置的提示信息。
//Deprecated: "will be deleted in version 2.0",
// 注解,用于代码层面的命令分组,不会显示在命令行输出中
Annotations: map[string]string{
"group": "user",
"require-auth": "none",
},
SilenceErrors: true,
//SilenceUsage: true,
// Version 定义版本
Version: "1.0.0",
// 是否禁用选项解析
//DisableFlagParsing: true,
//DisableAutoGenTag: true,
// PersistentPreRun: func(cmd *cobra.Command, args []string) {
// fmt.Println("hahha! let me check echk")
// },
PersistentPreRunE: func(cmd *cobra.Command, args []string) error {
// return errors.New("invalid parameter")
return nil
},
// 子命令执行过程
// Run: func(cmd *cobra.Command, args []string) {
// fmt.Println(strings.Join(args, " "))
// },
RunE: func(cmd *cobra.Command, args []string) error {
fmt.Println(strings.Join(args, " "))
return nil
},
PostRun: func(cmd *cobra.Command, args []string) {
fmt.Println("i am post run")
},
}
// 添加子命令根命令
rootCmd.AddCommand(&echoCmd)
// 执行根命令
rootCmd.Ex ecute()
}

