golang项目搭建笔记-cobra

发布时间 2023-09-17 20:17:41作者: 季夏三

cobra介绍

GitHub地址

cobra中,一个命令主要概念为command,arguement,flag,可以理解为谓语、宾语、状语

格式为APPNAME COMMAND ARG --FLAG,例如:

git clone URL --bare

项目搭建

cobra提供了非常方便的工具cobra-cli,可以快速添加命令,参考官方文档

  1. 新建项目

    # 进入项目目录
    go mod init github.com/{your name}/{your project name}
    
  2. 添加依赖

    go get -u github.com/spf13/cobra@latest
    
  3. 安装cobra-cli

    go install github.com/spf13/cobra-cli@latest
    
  4. 使用cobra-cli进行项目初始化

    cobra-cli init
    

    此时已经自动创建好了main.go、cmd目录、LICENSE文件,项目目录结构为

    .
    ├── LICENSE
    ├── cmd
    │   └── root.go
    ├── go.mod
    ├── go.sum
    └── main.go
    
  5. 使用cobra-cli添加命令

    # cobra-cli add [command name]
    cobra-cli add greet
    

    此时在cmd目录下多了个hi.go文件

    .
    ├── LICENSE
    ├── cmd
    │   ├── greet.go
    │   └── root.go
    ├── go.mod
    ├── go.sum
    └── main.go
    

    测试运行

    go run . greet
    # 运行结果
    # greet called
    

    也可添加子命令,如:

    cobra-cli add hi -p greetCmd
    

    此时目录结构:

    .
    ├── LICENSE
    ├── cmd
    │   ├── greet.go
    │   ├── hi.go
    │   └── root.go
    ├── go.mod
    ├── go.sum
    └── main.go
    

    hi.go文件中使用greetCmd.AddCommand(hiCmd)声明了命令的父子关系。

理解command

以hi.go为例,首先定义了一个cobra.Command{}结构体:

// hiCmd represents the hi command
var hiCmd = &cobra.Command{
	Use:   "hi",
	Short: "A brief description of your command",
	Long: `A longer description that spans multiple lines and likely contains examples
and usage of using your command. For example:

Cobra is a CLI library for Go that empowers applications.
This application is a tool to generate the needed files
to quickly create a Cobra application.`,
	Run: func(cmd *cobra.Command, args []string) {
		fmt.Println("hi called")
	},
}

运行帮助命令go run . greet hi -h,控制台显示:

A longer description that spans multiple lines and likely contains examples
and usage of using your command. For example:

Cobra is a CLI library for Go that empowers applications.
This application is a tool to generate the needed files
to quickly create a Cobra application.

Usage:
  Learn_Cobra greet hi [flags]

Flags:
  -h, --help   help for hi

Use

Use属性第一个单词为实际命令,后面的为介绍(经测试,这个介绍只是起一个展示作用,与实际语法无关,后文会介绍。),比如修改Use属性为:

...
	Use:   "hi this is a sentence",
...

运行帮助命令go run . greet hi -h,控制台显示:

...
Usage:
  Learn_Cobra greet hi this is a sentence [flags]
...

这个只是测试,不推荐这么写,记得改回去。

一般Use属性推荐使用固定语法,可见源码command.go:

...
	// Use is the one-line usage message.
	// Recommended syntax is as follows:
	//   [ ] identifies an optional argument. Arguments that are not enclosed in brackets are required.
	//   ... indicates that you can specify multiple values for the previous argument.
	//   |   indicates mutually exclusive information. You can use the argument to the left of the separator or the
	//       argument to the right of the separator. You cannot use both arguments in a single use of the command.
	//   { } delimits a set of mutually exclusive arguments when one of the arguments is required. If the arguments are
	//       optional, they are enclosed in brackets ([ ]).
	// Example: add [-F file | -D dir]... [-f format] profile
	Use string
...

Short、Long

顾名思义,略

Run

这是程序实际开始执行的地方。

尝试打印参数列表:

...
	Run: func(cmd *cobra.Command, args []string) {
		fmt.Println(args)
		fmt.Println("hi called")
	},
...

运行

go run . greet hi 12 32
# 运行结果
# [12 32]
# hi called

怎么获取flags见下文。

设置命令父子关系

init()方法中,第一行代码就是设置子命令的代码:

...
	greetCmd.AddCommand(hiCmd)
...

初学者需要注意,init()方法是在一个包被导入的时候,自动调用的函数,所以这里给Command做一些加工。

设置flags

PersistentFlags VS Flags

PersistentFlags是可以被子命令继承的特殊的Flag,而Flag只能在当前命令中使用,两者都可以通过Flags()获取值,只有在当前命令定义时,才能使用PersistentFlags()获取值。

设置flags

每种数据类型都有各种定义的方法,以string类型为例:

  • String(name string, value string, usage string)

    基本方法,定义了flag名称、默认值、使用描述。

  • StringP(name, shorthand string, value string, usage string)

    比第一种多了一个shorthand,短文本,只支持一个ASCII字符,使用时只需要一个短横线“-”。

  • StringVar(p *string, name string, value string, usage string)

    比第一种多了一个指向一个字符串变量的指针,读取的flag值会赋值到对应的字符串变量。

  • StringVarP(p *string, name, shorthand string, value string, usage string)

    第二种和第三种的结合体

示例,修改hi.go文件:

// hiCmd represents the hi command
var hiCmd = &cobra.Command{
	Use:   "hi",
	Short: "A brief description of your command",
	Long:  `A longer description`,
	Run: func(cmd *cobra.Command, args []string) {
		aa, _ := cmd.Flags().GetString("aa")
		bb, _ := cmd.Flags().GetString("bb")
		cc, _ := cmd.Flags().GetString("cc")
		fmt.Println(aa, bb, cc, s)
	},
}

var s string

func init() {
	greetCmd.AddCommand(hiCmd)

	hiCmd.Flags().String("aa", "default a", "this is flag a")
	hiCmd.Flags().StringP("bb", "b", "default b", "this is flag b")
	hiCmd.Flags().StringVar(&s, "cc", "default c", "this is flag c")
}

查看帮助:

go run . greet hi -h
...
Flags:
      --aa string   this is flag a (default "default a")
  -b, --bb string   this is flag b (default "default b")
      --cc string   this is flag c (default "default c")
  -h, --help        help for hi
...

运行:

go run . greet hi --aa hello
# hello default b default c default c

总结

知识根据cobre-cli生成的内容进行总结,后续会学viper,再和cobra整合。