mcpField
G
go-cobra

go-cobra

github.com/aaronflorey开发275 次安装25 周前更新
代码仓库

关于 go-cobra

面向使用 spf13/cobra 构建和调试 Go 命令行应用的参考技能,涵盖命令结构、标志、参数校验、补全、文档生成及常见模式。

主要功能

  1. 01搭建命令与子命令
  2. 02配置本地和持久标志
  3. 03校验位置参数
  4. 04说明生命周期钩子与错误处理
  5. 05生成 Shell 补全和文档

适用场景

  1. 01为 Go 应用添加命令
  2. 02实现 CLI 标志和参数检查
  3. 03创建 Shell 补全或命令文档

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/aaronflorey/agent-skills --skill go-cobra

安装后在 Claude Code 中输入/go-cobra确认已加载。

包含的文件

除 SKILL.md 外,安装时一起下载的参考资料和脚本。

references/
advanced.md
completions.md
docgen.md
viper-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(&region, "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
}

生命周期钩子

钩子按以下顺序执行:

  1. PersistentPreRun(由子命令继承)
  2. PreRun
  3. Run
  4. PostRun
  5. PersistentPostRun(由子命令继承)
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 — 高级模式和边缘情况

评论

支持 Markdown