简介
cobra是一个命令行程序库,可以用来编写命令行程序。同时,它也提供了一个脚手架,
用于生成基于 cobra 的应用程序框架。非常多知名的开源项目使用了 cobra 库构建命令行,如Kubernetes、Hugo、etcd等等等等。
本文介绍 cobra 库的基本使用和一些有趣的特性。
关于作者spf13,这里多说两句。spf13 开源不少项目,而且他的开源项目质量都比较高。
相信使用过 vim 的都知道spf13-vim,号称 vim 终极配置。
可以一键配置,对于我这样的懒人来说绝对是福音。他的viper是一个完整的配置解决方案。
完美支持 JSON/TOML/YAML/HCL/envfile/Java properties 配置文件等格式,还有一些比较实用的特性,如配置热更新、多查找目录、配置保存等。
还有非常火的静态网站生成器hugo也是他的作品。
快速使用
第三方库都需要先安装,后使用。下面命令安装了cobra
生成器程序和 cobra 库:
$ go get github.com/spf13/cobra/cobra
如果出现了golang.org/x/text
库找不到之类的错误,需要手动从 GitHub 上下载该库,再执行上面的安装命令。我以前写过一篇博客搭建 Go 开发环境提到了这个方法。
我们实现一个简单的命令行程序 git,当然这不是真的 git,只是模拟其命令行。最终还是通过os/exec
库调用外部程序执行真实的 git 命令,返回结果。
所以我们的系统上要安装 git,且 git 在可执行路径中。目前我们只添加一个子命令version
。目录结构如下:
▾ get-started/
▾ cmd/
helper.go
root.go
version.go
main.go
root.go
:
package cmd
import (
"errors"
"github.com/spf13/cobra"
)
var rootCmd = &cobra.Command {
Use: "git",
Short: "Git is a distributed version control system.",
Long: `Git is a free and open source distributed version control system
designed to handle everything from small to very large projects
with speed and efficiency.`,
Run: func(cmd *cobra.Command, args []string) {
Error(cmd, args, errors.New("unrecognized command"))
},
}
func Execute() {
rootCmd.Execute()
}
version.go
:
package cmd
import (
"fmt"
"os"
"github.com/spf13/cobra"
)
var versionCmd = &cobra.Command {
Use: "version",
Short: "version subcommand show git version info.",
Run: func(cmd *cobra.Command, args []string) {
output, err := ExecuteCommand("git", "version", args...)
if err != nil {
Error(cmd, args, err)
}
fmt.Fprint(os.Stdout, output)
},
}
func init() {
rootCmd.AddCommand(versionCmd)
}
main.go
文件中只是调用命令入口:
package main
import (
"github.com/go-quiz/go-daily-lib/cobra/get-started/cmd"
)
func main() {
cmd.Execute()
}
为了编码方便,在helpers.go
中封装了调用外部程序和错误处理函数:
package cmd
import (
"fmt"
"os"
"os/exec"
"github.com/spf13/cobra"
)
func ExecuteCommand(name string, subname string, args ...string) (string, error) {
args = append([]string{subname}, args...)
cmd := exec.Command(name, args...)
bytes, err := cmd.CombinedOutput()
return string(bytes), err
}
func Error(cmd *cobra.Command, args []string, err error) {
fmt.Fprintf(os.Stderr, "execute %s args:%v error:%vn", cmd.Name(), args, err)
os.Exit(1)
}
每个 cobra 程序都有一个根命令,可以给它添加任意多个子命令。我们在version.go
的init
函数中将子命令添加到根命令中。
编译程序。注意,不能直接go run main.go
,这已经不是单文件程序了。如果强行要用,请使用go run .
:
$ go build -o main.exe
cobra 自动生成的帮助信息,very cool:
代码语言:javascript复制$ ./main.exe -h
Git is a free and open source distributed version control system
designed to handle everything from small to very large projects
with speed and efficiency.
Usage:
git [flags]
git [command]
Available Commands:
help Help about any command
version version subcommand show git version info.
Flags:
-h, --help help for git
Use "git [command] --help" for more information about a command.
单个子命令的帮助信息:
代码语言:javascript复制$ ./main.exe version -h
version subcommand show git version info.
Usage:
git version [flags]
Flags:
-h, --help help for version
调用子命令:
代码语言:javascript复制$ ./main.exe version
git version 2.19.1.windows.1
未识别的子命令:
代码语言:javascript复制$ ./main.exe clone
Error: unknown command "clone" for "git"
Run 'git --help' for usage.
编译时可以将main.exe
改成git
,用起来会更有感觉