🔥码云GVP开源项目 12k star Uniapp+ElementUI 功能强大 支持多语言、二开方便! 广告
[TOC] Cobra 是一个用于创建强大的现代 CLI 应用程序的库。 Cobra 用于许多 Go 项目,例如 Kubernetes、Hugo 和 GitHub CLI 等。 此列表包含更广泛的使用 Cobra 的项目列表。 Cobra提供: - 基于简单子命令的 CLI:应用程序服务器、应用程序获取等。 - 完全符合 POSIX 标准的标志(包括短版本和长版本) - 嵌套子命令 - 全局、局部和级联标志 - 智能建议(应用程序服务器...您是指应用程序服务器吗?) - 自动生成命令和标志的帮助 - 子命令的分组帮助 - 自动帮助标志识别 -h、--help 等。 - 为您的应用程序自动生成 shell 自动完成功能(bash、zsh、fish、powershell) - 为您的应用程序自动生成手册页 - 命令别名,以便您可以在不破坏它们的情况下进行更改 - 灵活定义您自己的帮助、用法等。 - 可选与 viper 无缝集成 # 概念 Cobra 建立在命令(Commands)、参数(args)和标志(flags)的结构之上。 命令(Commands):代表动作 标志(flags):这些动作的修饰符 参数(args):事物 # 用户指南 要手动实现 Cobra,您需要创建一个裸 main.go 文件和一个 rootCmd 文件。 您可以选择提供您认为合适的其他命令。 ## 基本的cobra示例(根命令) 1. 初始项目 ```shell $ go mod init [项目名称] $ go get -u github.com/spf13/cobra ``` 2. 创建rootCmd 您将其放置在 `./cmd/root.go` 中: ```go package cmd import ( "fmt" "github.com/spf13/cobra" ) var rootCmd = &cobra.Command{ // 命令名字 Use: "mytools", // 简短描述,体现到 `Available Commands` 的说明。 // 注意:根目录不起作用 Short: "personnel management system", // 详细描述,体现到帮助文档的第一行信息 Long: "You can view/modify personnel information through mytools", // 版本号 Version: "1.1.0", // 命令处理业务逻辑 Run: func(cmd *cobra.Command, args []string) { fmt.Println("hello world") }, } // Execute 是命令的入口点 func Execute() { if err := rootCmd.Execute(); err != nil { fmt.Printf("err: %v\n", err) } } ``` 3. 创建main.go 您将其放置在 ./mian.go 中: ```go package main import ( "cobra/cmd" ) func main() { cmd.Execute() } ``` 4. 运行情况 ```shell # 执行命令 $ go run main.go hello world # 查看帮助文档 $ go run main.go -h You can view/modify personnel information through mytools Usage: mytools [flags] Flags: -h, --help help for mytools -v, --version version for mytools # 查看版本信息 $ go run main.go -v mytools version 1.1.0 ``` ## 子命令 1. 您将其放置在 `./cmd/add.go` 用下面的代码填充它: ```go package cmd import ( "fmt" "github.com/spf13/cobra" ) func init() { // 在rootCmd下添加子命令 rootCmd.AddCommand(addCmd) } var addCmd = &cobra.Command{ Use: "add", Short: "Add personnel", Long: "Add class personnel information", Run: func(cmd *cobra.Command, args []string) { fmt.Println("Add personnel") }, } ``` 2. 运行情况 ```bash # 查看帮助文档 ## 1. 根命令帮助文档 $ go run main.go -h You can view/modify personnel information through mytools Usage: mytools [flags] mytools [command] Available Commands: add Add personnel completion Generate the autocompletion script for the specified shell help Help about any command Flags: -h, --help help for mytools -v, --version version for mytools Use "mytools [command] --help" for more information about a command. ## 2. add子命令的帮助文档 $ go run main.go add -h Add class personnel information Usage: mytools add [flags] Flags: -h, --help help for add # 执行add子命令 $ go run main.go add Add personnel ``` ## 子命令别名 1. 在 `cobra.Command` 结构体添加 `Aliases` 字段信息, 例如在 `./cmd/add.go` 文件添加aliases字段 ```go Aliases: []string{"create"}, ``` 2. 运行情况 ```bash # 查看帮助文档 $ go run main.go create -h Add class personnel information Usage: mytools add [flags] Aliases: add, create Flags: -h, --help help for add # 执行create别名 $ go run main.go create Add personnel ``` ## flags标志 标志提供了修饰符来控制操作命令的操作方式,分为 本地标志 和 全局标志 1. 本地标志 语法:命令结构体.Flags().typeVarP(&变量名, 长参数, 短参数, 默认值, 参数说明) ```go func init() { // 在rootCmd下添加子命令 rootCmd.AddCommand(addCmd) // 在addCmd添加本地标志(addCmd.Flags) // 作用范围:只有addCmd才能使用 addCmd.Flags().StringVarP(&name, "name", "n", "", "Your name") } ``` 效果展示 ```bash # 查看帮助文档 $ go run main.go add -h Add class personnel information Usage: mytools add [flags] Aliases: add, create Flags: -h, --help help for add -n, --name string Your name ``` 2. 全局标志 语法:命令结构体.PersistentFlags().typeVarP(&变量名, 长参数, 短参数, 默认值, 参数说明) ```go func init() { // 在rootCmd下添加子命令 rootCmd.AddCommand(addCmd) // 在addCmd添加全局标志(addCmd.Flags) // 作用范围:addCmd及addCmd子命令下都生效 addCmd.PersistentFlags().Int8VarP(&age, "age", "a", 0, "Your age") } ``` 效果展示 ```bash # 查看add帮助文档 $ go run main.go add -h Add class personnel information Usage: mytools add [flags] Aliases: add, create Flags: -a, --age int8 Your age -h, --help help for add # 查看add的子命令帮助文档 $ go run main.go add test -h Usage: mytools add test [flags] Flags: -h, --help help for test Global Flags: -a, --age int8 Your age ``` 3. 必传flag标志 语法:命令结构体.MarkFlagRequired("长参数") ```go func init() { // 在rootCmd下添加子命令 rootCmd.AddCommand(addCmd) addCmd.Flags().StringVarP(&name, "name", "n", "", "Your name") // flags为name是必传项,name是要在命令结构体的flag标志(本地和全局都行) addCmd.MarkFlagRequired("name") } ``` 效果展示 ```bash $ go run main.go add Error: required flag(s) "name" not set Usage: mytools add [flags] mytools add [command] Aliases: add, create Available Commands: test Flags: -h, --help help for add -n, --name string Your name Use "mytools add [command] --help" for more information about a command. err: required flag(s) "name" not set ``` >[info] 没有 `name` 的flags标志位,报错信息提示在第一行与最后一行。中间都是帮助文档,提示不够简单明了。当然可以把中间的帮助信息屏蔽掉 解决方案:在 `命令结构体` 添加 `SilenceUsage` 参数 ```go // 在发生错误,不输出帮助信息 SilenceUsage: true, ``` 4. flags组合 语法:命令结构体.MarkFlagsRequiredTogether([]string{"长参数1", "长参数2"}...) ```go func init() { // 在rootCmd下添加子命令 rootCmd.AddCommand(addCmd) // name和age绑定为一个组,两个参数必须同时出现或都不出现。 addCmd.MarkFlagsRequiredTogether([]string{"name", "age"}...) } ``` 效果展示 ```bash # 不加上述绑定组的标志位 $ go run main.go add Add personnel # 添加其中一个 $ go run main.go add -n jiaxzeng Error: if any flags in the group [name age] are set they must all be set; missing [age] err: if any flags in the group [name age] are set they must all be set; missing [age] # flag组内的参数都添加 $ go run main.go add -n jiaxzeng -a 18 Add personnel ``` ## args参数 除了命令及flags标志之外,都匹配到args参数. >info args参数获取不需要任何代码,下面代码是复用add的子命令 ```go package cmd import ( "fmt" "github.com/spf13/cobra" ) var ( name string age int8 ) func init() { // 在rootCmd下添加子命令 rootCmd.AddCommand(addCmd) // 在addCmd添加本地标志(addCmd.Flags) // 作用范围:只有addCmd才能使用 addCmd.Flags().StringVarP(&name, "name", "n", "", "Your name") // 在addCmd添加全局标志(addCmd.Flags) // 作用范围:addCmd及addCmd子命令下都生效 addCmd.PersistentFlags().Int8VarP(&age, "age", "a", 0, "Your age") // name是flags必传项 addCmd.MarkFlagRequired("name") // name和age是捆绑项,要么一起出现,要么都不出现 addCmd.MarkFlagsRequiredTogether([]string{"name", "age"}...) } var addCmd = &cobra.Command{ Use: "add", Aliases: []string{"create"}, Short: "Add personnel", Long: "Add class personnel information", Run: func(cmd *cobra.Command, args []string) { fmt.Println("Add personnel") }, SilenceUsage: true, } ``` 效果演示 ```bash # 不传任何flag标志 $ go run main.go add ls wd Add personnel name: , age: 0, args: [ls wd] # args可以放在随意的位置 $ go run main.go add -n jiaxzeng kjflsd -a 18 Add personnel name: jiaxzeng, age: 18, args: [kjflsd] $ go run main.go add fljkew -n jiaxzeng -a 18 Add personnel name: jiaxzeng, age: 18, args: [fljkew] $ go run main.go add -n jiaxzeng -a 18 fjklsd Add personnel name: jiaxzeng, age: 18, args: [fjklsd] $ go run main.go add -n jiaxzeng kdl fdkls -a 18 fjk Add personnel name: jiaxzeng, age: 18, args: [kdl fdkls fjk] ``` ## 自定义帮助文档(-h, --help) ```go package cmd import ( "github.com/spf13/cobra" ) var getCmdHelp string = ` This is test help doc. ` func init() { rootCmd.AddCommand(getCmd) // 自定义帮助文档 getCmd.SetHelpTemplate(getCmdHelp) } var getCmd = &cobra.Command{ Use: "get", Short: "get personnel", Long: "get class personnel information", Run: func(cmd *cobra.Command, args []string) { }, } ``` 演示效果 ```bash # 查看帮助文档1 $ go run main.go get -h This is test help doc. # 查看帮助文档2 $ go run main.go get --help This is test help doc. ``` ## 未传参数和flags,打印帮助文档 >[info] flags没有设置必传项,不传任何信息都可以执行命令,这种不太符合使用习惯。一般习惯是不传任何参数的时候,希望输出命令或子命令的帮助文档。 在 命令结构体 的 `Run` 字段判断下参数即可 ```go package cmd import ( "fmt" "github.com/spf13/cobra" ) func init() { rootCmd.AddCommand(getCmd) getCmd.Flags().StringVarP(&name, "name", "n", "", "Your name") getCmd.Flags().Int8VarP(&age, "age", "a", 0, "Your age") } var getCmd = &cobra.Command{ Use: "get", Short: "get personnel", Long: "get class personnel information", Run: func(cmd *cobra.Command, args []string) { // 判断是否有传args与flags标志位 // 判断成功则查看帮助文档,如果失败则执行命令 if len(args) == 0 && (name == "" && age == int8(0)) { cmd.Help() } else { fmt.Printf("name: %v, age: %v\n", name, age) } }, } ``` 效果演示 ```bash # 不带args和flags标志位 $ go run main.go get get class personnel information Usage: mytools get [flags] Flags: -a, --age int8 Your age -h, --help help for get -n, --name string Your name # 带上flags标志 $ go run main.go get -n jiaxzeng -a 18 name: jiaxzeng, age: 18 # 带上args $ go run main.go get 123 name: , age: 0 ``` # 补全命令 ```shell source <(kvmmanager completion bash) ``` > 依赖于宿主机有安装 `bash-completion` 包,需要重新登录用户 # 在线文档 Golang pkg:https://pkg.go.dev/github.com/spf13/cobra GitHub:https://github.com/spf13/cobra