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() }