cobra 是由 spf13 大佬写的一个开发客户端工具的 golang 库,通过 cobra 可以很方便的开发可执行文件。源码地址:https://github.com/spf13/cobra
概念
Cobra 是建立在一系列的命令、参数和标识之上的库。
- Commands 代表的是动作
- Args 代表的是这个动作需要的事务
- Flags 表示动作的修饰
一个好的命令工具,读起来应该像一个句子一样,比如:
git clone URL --bare
# git 就是可执行文件名
# clone 就是命令(Command)
# URL 就是事务(Arg)
# --bare 就是修饰动作的Flag
Commands
Command 结构定义如下(仅仅列出了常用的):
type Command struct {
// 使用单行去显示这个命令的使用信息。
// 推荐的语法如下:
// [ ] 标识一个可选的flag。
// ... 表示前面的参数可以出现多次
// | 使用分割线表示互斥的信息
// Example: add [-F file | -D dir]... [-f format] profile
Use string
// 别名数组,和上面 Use 的第一个字符串意义相同
Aliases []string
// help 输出的短描述
Short string
// help 输出的长描述
Long string
// 使用例子
Example string
// 期望参数校验
Args PositionalArgs
// 如果某个命令废弃了 则使用这个命令的时候打印
Deprecated string
Version string
// The *Run functions are executed in the following order:
// * PersistentPreRun()
// * PreRun()
// * Run()
// * PostRun()
// * PersistentPostRun()
// All functions get the same args, the arguments after the command name.
//
// PersistentPreRun: children of this command will inherit and execute.
PersistentPreRun func(cmd *Command, args []string)
// PersistentPreRunE: PersistentPreRun but returns an error.
PersistentPreRunE func(cmd *Command, args []string) error
// PreRun: children of this command will not inherit.
PreRun func(cmd *Command, args []string)
// PreRunE: PreRun but returns an error.
PreRunE func(cmd *Command, args []string) error
// Run: Typically the actual work function. Most commands will only implement this.
Run func(cmd *Command, args []string)
// RunE: Run but returns an error.
RunE func(cmd *Command, args []string) error
// PostRun: run after the Run command.
PostRun func(cmd *Command, args []string)
// PostRunE: PostRun but returns an error.
PostRunE func(cmd *Command, args []string) error
// PersistentPostRun: children of this command will inherit and execute after PostRun.
PersistentPostRun func(cmd *Command, args []string)
// PersistentPostRunE: PersistentPostRun but returns an error.
PersistentPostRunE func(cmd *Command, args []string) error
}
Flags
Cobra 的 flag 解析由 pflag library 完成。符合 POSIX-compliant flags 和 Go flag package 标准。
安装
使用 go get
安装cobra:
go get -u github.com/spf13/cobra/cobra
之后,使用下列代码在你的应用中使用 cobra:
import "github.com/spf13/cobra"
实战
通常使用 Cobra 的应用,一般的文件架构如下:
▾ appName/
▾ cmd/
add.go
your.go
commands.go
here.go
main.go
在 main.go 中,我们只需要编写如下代码:
package main
import (
"path/cmd"
)
func main() {
cmd.Execute()
}
创建应用
我们开始以实战创建一个 cobra 项目。
我们开一个 tools 工具,该工具具有如下功能:
tools [command]
- time 打印当前时间
-f format 格式化打印当前时间
首先,我们先创建一个tools应用。
mkdir -p ${GO_PATH}/src/github.com/tools/cmd
cd ${GO_PATH}/src/github.com/tools
go mod init github.com/tools
然后我们在 tools 目录下创建 tools.go
,在 cmd 目录下创建 time.go
.
我们的目录层次如下:
.
├── cmd
│ └── time.go
├── go.mod
└── tools.go
编写代码
main.go
里面的逻辑比较简单,代码如下:
package main
import (
"github.com/tools/cmd"
"log"
)
func main() {
tools := cmd.NewToolsCommand()
if err := tools.Execute(); err != nil {
log.Fatal(err)
}
}
接下来编写 time.go
.
我们需要先编写 tools 这个工具:
rootCmd := &cobra.Command{
Use: "tools",
Long: "tools 工具有很多用法,期待你的探索",
Run: func(cmd *cobra.Command, args []string) {
fmt.Println("欢迎使用 tools 工具")
},
}
然后编写 time
子命令:
timeCmd := &cobra.Command{
Use: "time [-f format]",
Short: "time 子命令可以打印时间",
Long: "time 子命令是tools工具的一大特点,你可以使用time子命令灵活的输出当前时间",
Example: "tools time [-f format]",
Run: func(cmd *cobra.Command, args []string) {
fmt.Println(time.Now())
},
}
由于我们需要使用 flags ,所以先定义一个 flag:
var format string
// Flags() 和 PersistentFlags()的区别是 前者只作用在当前命令,后者也会作用在子命令
// 参数分别是:标志结果、长选项、短选项、默认值、描述
timeCmd.Flags().StringVarP(&format, "format", "f", "2006-01-02 15:04:05", "desc")
// 如果我们希望这个flag必须要,可以使用 timeCmd.MarkFlagRequired("format")
定好了标识,我们就需要改写 time
命令的 RUN
:
func(cmd *cobra.Command, args []string) {
if format != "" {
fmt.Println(time.Now().Format(format))
return
}
fmt.Println(time.Now())
}
完整代码如下:
package cmd
import (
"fmt"
"github.com/spf13/cobra"
"time"
)
var (
format string
)
func NewToolsCommand() *cobra.Command {
rootCmd := &cobra.Command{
Use: "tools",
Long: "tools 工具有很多用法,期待你的探索",
Run: func(cmd *cobra.Command, args []string) {
fmt.Println("欢迎使用 tools 工具")
},
}
timeCmd := &cobra.Command{
Use: "time [-f format]",
Short: "time 子命令可以打印时间",
Long: "time 子命令是tools工具的一大特点,你可以使用time子命令灵活的输出当前时间",
Example: "tools time [-f format]",
Run: func(cmd *cobra.Command, args []string) {
if format != "" {
fmt.Println(time.Now().Format(format))
return
}
fmt.Println(time.Now())
},
}
timeCmd.Flags().StringVarP(&format, "format", "f", "2006-01-02 15:04:05", "格式化参数,612345")
rootCmd.AddCommand(timeCmd)
return rootCmd
}
我们使用 go build tools.go
, 然后运行:
$ go build tools.go
$ ./tools time
2020-08-26 16:03:37
$ ./tools time -f "2006/01/02 15:04:05"
2020/08/26 16:03:43
实战完成!
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。