Skip to content

Cobra

Cobra 是一个强大且流行的 Go 语言库,用于构建命令行应用。它被广泛用于很多大型项目,例如 Kubernetes。Cobra 提供了命令行标志、子命令、嵌套命令等功能,使得构建复杂的 CLI 应用变得简单。

1. 安装 Cobra

首先,安装 Cobra 包:

bash
go get -u github.com/spf13/cobra@latest

2. Cobra 的基本结构

Cobra 的应用结构通常由一个根命令 (rootCmd) 和多个子命令 (subcommand) 组成。

示例:一个简单的 Cobra CLI 应用

go
package main

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

func main() {
	// 创建根命令
	var rootCmd = &cobra.Command{
		Use:   "mycli",  // 命令名
		Short: "A simple CLI app",  // 简短描述
		Run: func(cmd *cobra.Command, args []string) {
			// 默认执行的操作
			fmt.Println("Hello from Cobra CLI!")
		},
	}

	// 创建一个子命令
	var greetCmd = &cobra.Command{
		Use:   "greet",  // 子命令名称
		Short: "Greet the user",  // 子命令描述
		Run: func(cmd *cobra.Command, args []string) {
			fmt.Println("Hello, User!")
		},
	}

	// 将子命令添加到根命令
	rootCmd.AddCommand(greetCmd)

	// 执行根命令
	if err := rootCmd.Execute(); err != nil {
		fmt.Println(err)
		os.Exit(1)
	}
}

在上面的代码中:

  • rootCmd 是根命令,执行 mycli 命令时会触发。
  • greetCmd 是子命令,执行 mycli greet 时触发。

3. 命令行标志

Cobra 支持标志参数(flags),可以用于获取命令行传递的参数。标志可以是简单的 -f,也可以是长格式的 --flag

示例:使用标志

go
package main

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

func main() {
	var name string

	// 创建根命令
	var rootCmd = &cobra.Command{
		Use:   "mycli",
		Short: "A simple CLI app",
		Run: func(cmd *cobra.Command, args []string) {
			// 使用 flag 获取命令行参数
			fmt.Printf("Hello, %s!\n", name)
		},
	}

	// 在根命令上添加一个标志 --name
	rootCmd.Flags().StringVarP(&name, "name", "n", "User", "Name of the user")

	// 执行根命令
	if err := rootCmd.Execute(); err != nil {
		fmt.Println(err)
		os.Exit(1)
	}
}

在这个例子中,--name 标志的默认值为 User,你可以通过 mycli --name=Alice 来修改它。

4. 子命令和子命令参数

Cobra 允许你定义多个子命令,每个子命令都有自己的标志和逻辑。

示例:创建多个子命令

go
package main

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

func main() {
	var name string

	// 创建根命令
	var rootCmd = &cobra.Command{
		Use:   "mycli",
		Short: "A CLI app with multiple commands",
	}

	// 创建 greet 子命令
	var greetCmd = &cobra.Command{
		Use:   "greet",
		Short: "Greet the user",
		Run: func(cmd *cobra.Command, args []string) {
			fmt.Printf("Hello, %s!\n", name)
		},
	}

	// 在 greet 命令上添加标志
	greetCmd.Flags().StringVarP(&name, "name", "n", "User", "Name of the user")

	// 创建 goodbye 子命令
	var goodbyeCmd = &cobra.Command{
		Use:   "goodbye",
		Short: "Say goodbye to the user",
		Run: func(cmd *cobra.Command, args []string) {
			fmt.Println("Goodbye!")
		},
	}

	// 将子命令添加到根命令
	rootCmd.AddCommand(greetCmd, goodbyeCmd)

	// 执行根命令
	if err := rootCmd.Execute(); err != nil {
		fmt.Println(err)
		os.Exit(1)
	}
}

在这个例子中:

  • greet 子命令允许用户通过 --name 标志自定义问候语。
  • goodbye 子命令则会输出 "Goodbye!"。

5. 命令的持久化和临时标志

  • 持久标志:应用于根命令或者多个子命令,通常用于设置全局性的参数。
  • 临时标志:只应用于某个命令,而不会传播到其他命令。

示例:持久标志 vs 临时标志

go
package main

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

func main() {
	var globalFlag string
	var greetCmd = &cobra.Command{
		Use:   "greet",
		Short: "Greet the user",
		Run: func(cmd *cobra.Command, args []string) {
			fmt.Printf("Hello, %s!\n", globalFlag)
		},
	}

	var rootCmd = &cobra.Command{
		Use:   "mycli",
		Short: "A CLI app with global and local flags",
	}

	// 添加持久标志
	rootCmd.PersistentFlags().StringVarP(&globalFlag, "global", "g", "User", "Global name for greeting")

	// 添加 greet 子命令
	rootCmd.AddCommand(greetCmd)

	// 执行根命令
	if err := rootCmd.Execute(); err != nil {
		fmt.Println(err)
		os.Exit(1)
	}
}

6. 自动生成帮助和完成

Cobra 自动为命令生成帮助文档,用户可以使用 --help 参数查看命令的帮助。

  • 查看根命令帮助:mycli --help
  • 查看某个子命令的帮助:mycli greet --help

7. 命令的执行顺序

Cobra 命令的执行顺序是从根命令到子命令逐层执行。如果在根命令中定义了 Run 函数,那么在没有子命令的情况下会执行该函数;如果有子命令,那么执行相应的子命令。

总结

  • Cobra 提供了一个清晰、结构化的方式来构建复杂的 CLI 应用。
  • 支持 命令子命令标志自动帮助文档 等特性。
  • Cobra 非常适合用于构建大型的、多命令的工具。