关于 go-cobra
面向使用 spf13/cobra 构建和调试 Go 命令行应用的参考技能,涵盖命令结构、标志、参数校验、补全、文档生成及常见模式。
主要功能
- 01搭建命令与子命令
- 02配置本地和持久标志
- 03校验位置参数
- 04说明生命周期钩子与错误处理
- 05生成 Shell 补全和文档
适用场景
- 01为 Go 应用添加命令
- 02实现 CLI 标志和参数检查
- 03创建 Shell 补全或命令文档
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ aaronflorey/ agent-skills --skill go-cobra安装后在 Claude Code 中输入/go-cobra确认已加载。
包含的文件
除 SKILL.md 外,安装时一起下载的参考资料和脚本。
references/advanced.mdcompletions.mddocgen.mdviper-integration.md详细介绍
Cobra CLI 框架技能
使用 spf13/cobra 库编写、搭建和调试 Go CLI 应用。当用户想要在 Go 中构建命令行界面、向 CLI 添加命令/子命令、处理标志(持久、局部、必需)、实现 Shell 补全、生成文档,或询问任何有关基于 Cobra 的 CLI 开发的问题时,都使用此技能——即使他们只是说“我想构建一个 CLI 工具”或“如何向我的 Go 应用添加命令”。
快速入门
安装
go get -u github.com/spf13/cobra@latest
安装 CLI 生成器(可选,但建议用于搭建项目):
go install github.com/spf13/cobra-cli@latest
项目结构
myapp/
cmd/
root.go # Root command and Execute()
version.go # Additional commands
serve.go
main.go # Just calls cmd.Execute()
最简 main.go
package main
import "myapp/cmd"
func main() {
cmd.Execute()
}
最简 root.go
package cmd
import (
"fmt"
"os"
"github.com/spf13/cobra"
)
var rootCmd = &cobra.Command{
Use: "myapp",
Short: "A brief description of your application",
Long: `A longer description that spans multiple lines.`,
Run: func(cmd *cobra.Command, args []string) {
fmt.Println("Hello from myapp!")
},
}
func Execute() {
if err := rootCmd.Execute(); err != nil {
fmt.Fprintln(os.Stderr, err)
os.Exit(1)
}
}
核心概念
命令代表操作。参数是操作对象。标志用于修改行为。
模式:APPNAME COMMAND ARG --FLAG
示例:
hugo server --port=1313— “server”是命令,“port”是标志git clone URL --bare— “clone”是命令,“URL”是参数,“bare”是标志
命令结构
创建命令
var serveCmd = &cobra.Command{
Use: "serve", // How to call it
Short: "Start the server", // One-line help
Long: `Detailed description here...`, // Full help text
Example: ` myapp serve --port 8080`, // Usage examples
Run: func(cmd *cobra.Command, args []string) {
// Command logic here
},
}
func init() {
rootCmd.AddCommand(serveCmd)
}
关键命令字段
| 字段 | 用途 |
|---|---|
Use | 用法模式:"command [args]" |
Aliases | 替代名称:[]string{"s", "srv"} |
Short | 帮助列表中的简短描述 |
Long | --help 的完整描述 |
Example | 用法示例(缩进 2 个空格) |
Run | 实际的命令逻辑 |
RunE | 与 Run 相同,但会返回错误 |
Args | 位置参数验证 |
ValidArgs | 用于 Shell 补全的静态列表 |
ValidArgsFunction | 动态补全函数 |
Hidden | 在帮助输出中隐藏 |
Deprecated | 标记为弃用并附上消息 |
Version | 版本字符串(启用 --version) |
Run 与 RunE
需要向调用方返回错误时,使用 RunE:
var tryCmd = &cobra.Command{
Use: "try",
Short: "Try something",
RunE: func(cmd *cobra.Command, args []string) error {
if err := doSomething(); err != nil {
return err // Error handled by Cobra
}
return nil
},
}
标志
标志类型
持久标志 — 当前命令及其所有子命令都可用:
rootCmd.PersistentFlags().StringVar(&cfgFile, "config", "", "config file path")
rootCmd.PersistentFlags().BoolVarP(&verbose, "verbose", "v", false, "verbose output")
局部标志 — 仅适用于当前命令:
serveCmd.Flags().IntVarP(&port, "port", "p", 8080, "port to listen on")
serveCmd.Flags().StringVar(&host, "host", "localhost", "host address")
标志方法
| 方法 | 示例 |
|---|---|
StringVar | --name value |
StringVarP | --name value 或 -n value |
BoolVar | --verbose(true)或 --verbose=false |
IntVar | --count 5 |
StringSliceVar | --tag a --tag b 或 --tag a,b |
StringArrayVar | --tag a --tag b(不会按逗号拆分) |
CountVarP | -v(1)、-vv(2)、-vvv(3) |
必需标志
cmd.Flags().StringVarP(®ion, "region", "r", "", "AWS region")
cmd.MarkFlagRequired("region")
// For persistent flags
cmd.MarkPersistentFlagRequired("config")
标志组
// Must be used together
cmd.MarkFlagsRequiredTogether("username", "password")
// Cannot be used together
cmd.MarkFlagsMutuallyExclusive("json", "yaml")
// At least one required
cmd.MarkFlagsOneRequired("json", "yaml")
// Exactly one required (combine both)
cmd.MarkFlagsOneRequired("json", "yaml")
cmd.MarkFlagsMutuallyExclusive("json", "yaml")
计数标志(详细程度模式)
var verbose int
func init() {
rootCmd.PersistentFlags().CountVarP(&verbose, "verbose", "v", "verbosity (-v, -vv, -vvv)")
}
// Usage:
// myapp -v → verbose = 1
// myapp -vv → verbose = 2
// myapp -vvv → verbose = 3
位置参数
内置验证器
cmd.Args = cobra.NoArgs // No args allowed
cmd.Args = cobra.ArbitraryArgs // Any args (default)
cmd.Args = cobra.MinimumNArgs(1) // At least N
cmd.Args = cobra.MaximumNArgs(3) // At most N
cmd.Args = cobra.ExactArgs(2) // Exactly N
cmd.Args = cobra.RangeArgs(1, 3) // Between min and max
cmd.Args = cobra.OnlyValidArgs // Only from ValidArgs list
组合验证器
cmd.Args = cobra.MatchAll(cobra.ExactArgs(2), cobra.OnlyValidArgs)
自定义验证器
cmd.Args = func(cmd *cobra.Command, args []string) error {
if len(args) < 1 {
return fmt.Errorf("requires at least 1 arg")
}
if !isValidInput(args[0]) {
return fmt.Errorf("invalid argument: %s", args[0])
}
return nil
}
生命周期钩子
钩子按以下顺序执行:
PersistentPreRun(由子命令继承)PreRunRunPostRunPersistentPostRun(由子命令继承)
var rootCmd = &cobra.Command{
Use: "app",
PersistentPreRun: func(cmd *cobra.Command, args []string) {
// Runs before every command (including subcommands)
initLogging()
},
PersistentPostRun: func(cmd *cobra.Command, args []string) {
// Runs after every command
cleanup()
},
}
var subCmd = &cobra.Command{
Use: "sub",
PreRun: func(cmd *cobra.Command, args []string) {
// Only for this command, before Run
},
Run: func(cmd *cobra.Command, args []string) {
// Main logic
},
}
使用 *RunE 变体来返回错误:
PersistentPreRunE: func(cmd *cobra.Command, args []string) error {
return initConfig()
}
Viper 集成
Cobra 可与 Viper 无缝集成,用于配置管理。完整文档请参阅 references/viper-integration.md。
import "github.com/spf13/viper"
func init() {
cobra.OnInitialize(initConfig)
rootCmd.PersistentFlags().StringVar(&cfgFile, "config", "", "config file")
rootCmd.PersistentFlags().String("author", "Me", "author name")
// Bind flag to viper - priority: flag > env > config > default
viper.BindPFlag("author", rootCmd.PersistentFlags().Lookup("author"))
}
func initConfig() {
if cfgFile != "" {
viper.SetConfigFile(cfgFile)
} else {
home, _ := os.UserHomeDir()
viper.AddConfigPath(home)
viper.SetConfigType("yaml")
viper.SetConfigName(".myapp")
}
viper.AutomaticEnv()
viper.ReadInConfig()
}
// IMPORTANT: Use viper.GetString("author"), not the flag variable
// Flag variables are NOT updated from config file values
帮助与用法
自动功能
- 自动添加
--help/-h标志 - 有子命令时自动添加
help子命令 - 拼写错误建议:
myapp srever→“您是不是想输入 ‘server’?”
自定义
// Custom help template
cmd.SetHelpTemplate(`Custom help: {{.Use}}`)
// Custom usage template
cmd.SetUsageTemplate(`Usage: {{.UseLine}}`)
// Custom help function
cmd.SetHelpFunc(func(cmd *cobra.Command, args []string) {
fmt.Println("Custom help!")
})
// Disable suggestions
cmd.DisableSuggestions = true
// Adjust suggestion distance
cmd.SuggestionsMinimumDistance = 1
版本标志
var rootCmd = &cobra.Command{
Use: "myapp",
Version: "1.0.0", // Enables --version flag
}
// Custom version template
cmd.SetVersionTemplate(`Version: {{.Version}}`)
命令分组
rootCmd.AddGroup(&cobra.Group{ID: "core", Title: "Core Commands:"})
rootCmd.AddGroup(&cobra.Group{ID: "util", Title: "Utility Commands:"})
serveCmd.GroupID = "core"
versionCmd.GroupID = "util"
Shell 补全
Cobra 会自动提供 completion 命令。Shell 补全实现的详细信息,请参阅 references/completions.md。
快速用法:
# Bash
source <(myapp completion bash)
# Zsh
myapp completion zsh > "${fpath[1]}/_myapp"
# Fish
myapp completion fish > ~/.config/fish/completions/myapp.fish
# PowerShell
myapp completion powershell | Out-String | Invoke-Expression
动态补全
cmd.ValidArgsFunction = func(cmd *cobra.Command, args []string, toComplete string) ([]cobra.Completion, cobra.ShellCompDirective) {
if len(args) != 0 {
return nil, cobra.ShellCompDirectiveNoFileComp
}
return []cobra.Completion{"option1", "option2"}, cobra.ShellCompDirectiveNoFileComp
}
文档生成
Cobra 可以生成 man 页面、Markdown 等。详情请参阅 references/docgen.md。
快速示例:
import "github.com/spf13/cobra/doc"
// Markdown
doc.GenMarkdownTree(rootCmd, "./docs")
// Man pages
header := &doc.GenManHeader{Title: "MYAPP", Section: "1"}
doc.GenManTree(rootCmd, header, "./man")
创建插件
适用于 kubectl 这类使用插件的工具(将 kubectl-myplugin 作为 kubectl myplugin 调用):
rootCmd := &cobra.Command{
Use: "kubectl-myplugin",
Annotations: map[string]string{
cobra.CommandDisplayNameAnnotation: "kubectl myplugin",
},
}
全局设置
// Enable case-insensitive command matching
cobra.EnableCaseInsensitive = true
// Enable prefix matching (dangerous for production)
cobra.EnablePrefixMatching = true
// Execute all parent hooks (not just first found)
cobra.EnableTraverseRunHooks = true
// Disable command sorting in help
cobra.EnableCommandSorting = false
测试命令
func TestServeCommand(t *testing.T) {
cmd := rootCmd
// Capture output
buf := new(bytes.Buffer)
cmd.SetOut(buf)
cmd.SetErr(buf)
// Set args
cmd.SetArgs([]string{"serve", "--port", "9000"})
// Execute
err := cmd.Execute()
if err != nil {
t.Fatalf("unexpected error: %v", err)
}
// Check output
if !strings.Contains(buf.String(), "expected") {
t.Errorf("unexpected output: %s", buf.String())
}
}
上下文支持
var rootCmd = &cobra.Command{
Use: "myapp",
Run: func(cmd *cobra.Command, args []string) {
ctx := cmd.Context()
// Use context for cancellation, timeouts, etc.
},
}
// Execute with context
ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
defer cancel()
rootCmd.ExecuteContext(ctx)
常见模式
子命令组织
对于大型应用,请将子命令组织在单独的包中:
cmd/
root.go
config/
config.go # Defines configCmd
get.go # config get
set.go # config set
// cmd/config/config.go
var ConfigCmd = &cobra.Command{Use: "config", Short: "Manage configuration"}
func init() {
ConfigCmd.AddCommand(getCmd)
ConfigCmd.AddCommand(setCmd)
}
// cmd/root.go
import "myapp/cmd/config"
func init() {
rootCmd.AddCommand(config.ConfigCmd)
}
错误处理
func Execute() {
if err := rootCmd.Execute(); err != nil {
// Error already printed by Cobra
os.Exit(1)
}
}
// To silence automatic error printing:
rootCmd.SilenceErrors = true
rootCmd.SilenceUsage = true
静默/安静模式
var quiet bool
func init() {
rootCmd.PersistentFlags().BoolVarP(&quiet, "quiet", "q", false, "suppress output")
}
func output(msg string) {
if !quiet {
fmt.Println(msg)
}
}
参考文件
有关特定主题的详细信息,请参阅:
references/completions.md— Shell 补全的实现细节references/docgen.md— 文档生成(man、markdown、yaml、rst)references/advanced.md— 高级模式和边缘情况