[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
- Golang簡介
- 開發環境
- Golang安裝
- 編輯器及快捷鍵
- vscode插件
- 第一個程序
- 基礎數據類型
- 變量及匿名變量
- 常量與iota
- 整型與浮點型
- 復數與布爾值
- 字符串
- 運算符
- 算術運算符
- 關系運算符
- 邏輯運算符
- 位運算符
- 賦值運算符
- 流程控制語句
- 獲取用戶輸入
- if分支語句
- for循環語句
- switch語句
- break_continue_goto語法
- 高階數據類型
- pointer指針
- array數組
- slice切片
- slice切片擴展
- map映射
- 函數
- 函數定義和調用
- 函數參數
- 函數返回值
- 作用域
- 函數形參傳遞
- 匿名函數
- 高階函數
- 閉包
- defer語句
- 內置函數
- fmt
- strconv
- strings
- time
- os
- io
- 文件操作
- 編碼
- 字符與字節
- 字符串
- 讀寫文件
- 結構體
- 類型別名和自定義類型
- 結構體聲明
- 結構體實例化
- 模擬構造函數
- 方法接收器
- 匿名字段
- 嵌套與繼承
- 序列化
- 接口
- 接口類型
- 值接收者和指針接收者
- 類型與接口對應關系
- 空接口
- 接口值
- 類型斷言
- 并發編程
- 基本概念
- goroutine
- channel
- select
- 并發安全
- 練習題
- 第三方庫
- Survey
- cobra