# 准备工作

安装 cobra-cli,会被安装到 %GOPATH%\bin\cobra-cli.exe(默认:C:\Users\你的用户名\go\bin\cobra-cli.exe


go install github.com/spf13/cobra-cli@latest

初始化工作

mkdir cobra-study
cd cobra-study
go mod init cobra-study
cobra-cli init

可以得到如下内容


PS C:\Users\Bondrewd\Desktop\Project\PAB\code_study\cobra-study> ls

    目录: C:\Users\Bondrewd\Desktop\Project\PAB\code_study\cobra-study

Mode                 LastWriteTime         Length Name
----                 -------------         ------ ----
d-----         2026/1/29     13:31                cmd
-a----         2026/1/29     13:31            187 go.mod
-a----         2026/1/29     13:31            900 go.sum
-a----         2026/1/29     13:31              0 LICENSE
-a----         2026/1/29     13:31            122 main.go

# Cobra 程序的三位一体

Cobra 的设计哲学非常直观,它将 CLI 命令抽象为 Commands(命令)Args(参数)Flags(标志)

  • Commands(命令):动作的本身。例如 app serve 中的 serve
  • Args(参数) :动作的对象。例如 app copy file.txt 中的 file.txt
  • Flags(标志) :动作的修饰。例如 app serve --port 8080 中的 --port

# 启动链条

cobra-cli启动链条


# 关键模块

# root.go

定义:


var rootCmd = &cobra.Command{
    Use  : "myapp [name]",
    Short: "一个简短的 demo",
    Long : `这是一个详细的描述,通常包含多行,用于解释该程序的复杂功能。`,
    // 核心执行逻辑
    Run  : func(cmd *cobra.Command, args []string) {
        if len(args) > 0 {
            fmt.Printf("你好, %s!\n", args[0])
        }
    },
}

这是你定义命令的地方。在 Win11 终端运行 .\myapp.exe --help 时,这些字段决定了用户看到的内容。

  • Use : 语法定义。第一个单词是命令名,后面是参数占位符。
  • Short: 简介。出现在子命令列表的右侧。
  • Long : 详述。当用户专门查看该命令帮助时显示的详细说明。
  • Run : 函数闭包,它的主要职责是:
    • 承接逻辑:当用户在终端输入命令并按下回车后,Cobra 解析完参数就会跳转到这里执行。
    • 访问数据:它可以直接读取解析后的 args(位置参数)以及在 init() 中绑定的 flags 变量。
    • 触发业务:通常我们会在 Run 里面调用其他的函数(如数据库操作、API 请求等)。

字段名

函数签名

适用场景

Run

func(cmd *Command, args []string)

简单逻辑,不需要返回错误。

RunE

func(cmd *Command, args []string) error

最推荐。如果执行出错,返回 error,Cobra 会自动帮你打印错误。

PostRun

func(cmd *Command, args []string)

执行完主逻辑后的收尾工作(如关闭日志文件)。

PreRun

func(cmd *Command, args []string)

执行主逻辑前的准备工作(如检查用户是否登录)。


# init():参数的“预装配”

在 Go 中,init() 函数会在 main() 函数执行之前运行。


func init() {
    rootCmd.Flags().BoolP("toggle", "t", false, "Help message for toggle")
}
  • 为什么要在init()中定义 Flags? Cobra 需要在程序正式跑起来之前,就知道有哪些参数需要解析。如果在 Run 里才定义,程序根本不知道 --port 是合法的。

  • init()执行顺序

    1. 变量初始化rootCmd 变量被创建。
    2. init() 执行:将 Flags 绑定到 rootCmd
    3. main() 执行:调用 Execute()

# Execute():连接器

Execute()函数:


func Execute() {
err := rootCmd.Execute()
if err != nil {
os.Exit(1)
}
}
  • 连接 maincmd:在 Win11 下,入口是 main.go。它只有一行代码 cmd.Execute()。这行代码会跳转到 root.go 中,启动 Cobra 的引擎。
  • 职责:解析命令行输入的参数、匹配命令、并最终触发对应的 Run 函数。

# Flags 的两种状态

init() 中可以定义Flags 的两种状态:

# Persistent Flags(持久标志/全局标志)

  • 特性:具有向下传递性。如果定义在 rootCmd 上,那么所有的子命令(如 serve, config)都可以使用这个标志。
  • 适用场景:全局配置,如 --config 配置文件路径、--verbose 日志级别。

# Local Flags(本地标志)

  • 特性:具有独占性。只在定义的当前命令中生效,子命令无法继承。
  • 适用场景:特定功能的修饰,如 serve 命令特有的 --port

一个例子,假设你的程序叫 myapp,你在 root.goinit() 中定义:


func init() {
    // 1. Persistent Flag: 即使运行子命令,也能用 --token
    rootCmd.PersistentFlags().StringVar(&token, "token", "", "用户验证令牌")

    // 2. Local Flag: 只有运行 myapp 本身(不带子命令)时才能用 --mode
    rootCmd.Flags().StringVar(&mode, "mode", "fast", "运行模式")
}

# 参数校验 (Args Validation)

Args 是指那些不带横杠的“裸字符串”(如 myapp copy file1 file2 中的两个文件名)。参数校验就是给你的程序加一道“安检”,防止用户乱传参数。

Cobra 提供了多种内置的校验器,直接写在 Command 结构体中:

  • cobra.NoArgs : 不允许任何参数(只能用 Flags)。
  • cobra.ExactArgs(n) : 必须且只能传 n 个参数。
  • cobra.MinimumNArgs(n): 至少传 n 个参数。
  • cobra.MaximumNArgs(n): 至多传 n 个参数。
  • cobra.RangeArgs(min, max): 参数数量必须在范围内。

一个例子,我们要写一个“加法”命令,必须输入且只能输入 2 个数字:


var addCmd = &cobra.Command{
    Use:   "add [num1] [num2]",
    Short: "计算两个数相加",
    // 关键点:强制要求 2 个参数
    Args:  cobra.ExactArgs(2),
    Run: func(cmd *cobra.Command, args []string) {
        fmt.Printf("结果是: %s + %s\n", args[0], args[1])
    },
}

# 简单的例子

# 无子命令

这是你在 root.go 中可以尝试的最简结构,修改成如下下内容:


package cmd

import (
    "fmt"
    "github.com/spf13/cobra"
)

var name string // 用于接收 Flag 的变量

var rootCmd = &cobra.Command{
    Use:   "hello",
    Short: "向某人打招呼",
    Run: func(cmd *cobra.Command, args []string) {
        // 逻辑处理
        fmt.Printf("你好 %s, 欢迎来到 Go 世界!\n", name)
    },
}

// 供 main.go 调用
func Execute() {
    rootCmd.Execute()
}

func init() {
    // 定义一个持久标志 --name 或 -n
    rootCmd.PersistentFlags().StringVarP(&name, "name", "n", "陌生人", "输入你的名字")
}
  • 编译go build -o hello.exe
  • 运行默认值.\hello.exe → 输出:你好 陌生人…
  • 使用 Flag.\hello.exe --name Bondrewd → 输出:你好 Bondrewd…

输出示例:


PS C:\Users\Bondrewd\Desktop\Project\PAB\code_study\cobra-study> .\hello.exe -h
向某人打招呼

Usage:
  hello [flags]

Flags:
  -h, --help          help for say
  -n, --name string   输入你的名字 (default "陌生人")

# 多个子命令


package cmd

import (
    "fmt"
    "github.com/spf13/cobra"
    "time"
)

// 1. 定义根命令
var rootCmd = &cobra.Command{
    Use:   "toolbox",
    Short: "一个简单的例子",
    Long:  `这是一个集成了打招呼和计时功能的 Cobra 演示程序。`,
    // 根命令通常不写 Run,或者只打印帮助信息
}


// 2. 定义子命令 A:打招呼
var greetCmd = &cobra.Command{
    Use:   "greet [name]",
    Short: "向指定的人发送问候",
    // 参数校验:必须提供且只能提供 1 个参数(姓名)
    Args:  cobra.ExactArgs(1),
    Run: func(cmd *cobra.Command, args []string) {
        fmt.Printf("Hello, %s! 欢迎学习 Cobra。\n", args[0])
    },
}

// 3. 定义子命令 B:计时器
var timerCmd = &cobra.Command{
    Use:   "timer [seconds]",
    Short: "简单的倒计时工具",
    Args:  cobra.ExactArgs(1),
    Run: func(cmd *cobra.Command, args []string) {
        fmt.Printf("倒计时开始: %s 秒\n", args[0])
        // 简单的倒计时逻辑(仅作演示)
        time.Sleep(1 * time.Second)
        fmt.Println("时间到!")
    },
}

// 4. 在 init 中组装它们
func init() {
    // 将子命令添加到根命令中
    rootCmd.AddCommand(greetCmd)
    rootCmd.AddCommand(timerCmd)

    // 添加一个 Persistent Flag (全局可用)
    rootCmd.PersistentFlags().BoolP("verbose", "v", false, "显示详细日志")
}

func Execute() {
    rootCmd.Execute()
}

输出示例:


PS C:\Users\Bondrewd\Desktop\Project\PAB\code_study\cobra-study> .\tset-cli.exe
这是一个集成了打招呼和计时功能的 Cobra 演示程序。

Usage:
  toolbox [command]

Available Commands:
  completion  Generate the autocompletion script for the specified shell
  greet       向指定的人发送问候
  help        Help about any command
  timer       简单的倒计时工具

Flags:
  -h, --help      help for toolbox
  -v, --verbose   显示详细日志

Use "toolbox [command] --help" for more information about a command.

------------------------------------------------------------
PS C:\Users\Bondrewd\Desktop\Project\PAB\code_study\cobra-study> .\tset-cli.exe timer 5
倒计时开始: 5 秒
时间到!

------------------------------------------------------------
PS C:\Users\Bondrewd\Desktop\Project\PAB\code_study\cobra-study> .\tset-cli.exe greet PAB
Hello, PAB! 欢迎学习 Cobra。