Cobra is the most popular command-line library for golang, see the documentation
1. Scaffolding
mkdir pt && cd pt && go mod init
cobra-cli init # 在项目下运行即可生成脚手架
# tree
.
├── LICENSE
├── cmd # 生成了cmd目录
│ └── root.go # 生成了root.go, 其中定义了rootCmt变量
├── go.mod
├── go.sum
└── main.go
# go run main.go
Usage:
pt [command]
Available Commands:
completion Generate the autocompletion script for the specified shell
help Help about any command
show Display current time
Flags:
-h, --help help for pt
-t, --toggle Help message for toggle
2. Child instruction
# cobra-cli add show # 添加名为show的子命令, 则会自动生成cmd/show.go代码
# go run main.go show # 执行名为show的子命令
2023-08-28 22:00:58.263991 +0800 CST m=+0.000923251
# go run main.go show -h # 获取名为show的子命令的帮助信息
will display like 2023-08-28 22:00:58.263991 +0800 CST m=+0.000923251
Usage:
pt show [flags]
Flags:
-h, --help help for show
Three, flag parameter
3.1 Definition
// 添加参数
func init() {
rootCmd.AddCommand(proto2jsonCmd)
proto2jsonCmd.Flags().StringP("content", "c", "", "byte content of a.proto")
proto2jsonCmd.Flags().StringP("filepath", "f", "", "filepath of proto file")
}
// 输出如下:
with a.proto protocol
Usage:
pt p2j [flags]
Flags:
-c, --content string byte content of a.proto
-f, --filepath string filepath of proto file
-h, --help help for p2j
3.2 use
If you need to use a global flag or a local flag, you need to define a variable in the appropriate scope to store the flag value, so that the flag can take effect in a specific scope.
3.2.1 Using global flags
To make a flag effective for all commands, you need to create a variable in the root.go file to store the flag value.
If you need to define a global flag name:
// 在root.go 文件中添加一个变量name
var name string
// 在init函数中添加全局flag,将flag值存储到变量name中
rootCmd.PersistentFlags().StringVar(&name, "name", "", "set name")
// 在子命令version的Run方法中输出name
Run: func(cmd *cobra.Command, args []string) {
fmt.Println("name is: ", name)
}
// 执行命令
./demo version --name a
输出:
name is: a
3.2 Using local flags
To make a flag effective for a certain command, a variable needs to be created in the command file to store the flag value.
If you need to define a local flag name for the version command:
// 定义变量content
var content string
// 在version.go的init函数中添加flag
versionCmd.Flags().StringVarP(&content, "content", "s", "false", "you are my sunshine")
// 在子命令version.go的Run方法中输出
Run: func(cmd *cobra.Command, args []string) {
fmt.Println("name is: ", name)
fmt.Println("content is: ", content)
}
// 执行命令
./demo version --name a --content b
输出:
name is: a
content is: b
3.3 cmd can only access the flag value defined by itself
Note: If flags are stored in local variables, then other commands "cannot" use the local flag of a command. Although the local flag is defined in a command file as a local variable, other files under the cmd folder can access this variable, but if other commands do not define their own local flags to obtain the same flag value, the obtained value is the The zero value of a local variable. Examples are as follows:
// 1. 添加一个新命令helloworld
> cobra add helloworld
// 2.输出content值
Run: func(cmd *cobra.Command, args []string) {
fmt.Println("content is: ", sunshine)
}
// 3.执行命令
> ./demo helloworld --content b
Error: unknown flag: --content // 输出错误未知flag, 原因就是该命令并未定义名为content的局部flag
3.4 required flag
// init文件中增加flag定义
versionCmd.Flags().StringVarP(&sunshine, "content", "c", "", "my content")
versionCmd.MarkFlagRequired("content")
// 执行
> ./demo version
// 输出
Error: required flag(s) "content" not set // 说明必须要设置flag content
// 传入content flag
> ./demo version --content b // 输出: content is: b
3.5 Global flag configuration
MinimumNArgs(int) 当参数数目低于配置的最小参数个数时报错
MaximumNArgs(int) 当参数数目大于配置的最大参数个数时报错
ExactArgs(int) 如果参数数目不是配置的参数个数时报错
NoArgs 没有参数则报错
Examples are as follows:
// 添加一个命令path
> cobra add path
// 设置该命令需要且仅需要一个参数,并在Run方法中取出参数
var pathCmd = &cobra.Command{
Use: "path [path]",
Short: "A brief description of your command",
Long: "",
Args: cobra.ExactArgs(1),
Run: func(cmd *cobra.Command, args []string) {
fmt.Println("path called")
fmt.Println("path:", args[0])
},
}
// 执行命令并输出
> ./demo path /home // 输出path: /home