spf13/cobra 和 urfave/cli 是Go的2个最流行的优秀的命令行工具
对比 |
spf13/cobra |
urfave/cli |
简介 |
A Framework for Modern CLI Apps in Go |
urfave/cli is a simple, fast, and fun package for building command line apps in Go. |
应用项目 |
docker, kubernetes, istio, etcd, hugo … |
drone, peach, gogs, gitea … |
LICENSE |
Apache 2.0 license |
MIT |
flag |
基于pflag, 支持更多类型参数 |
基于标准库flag |
绑定配置参数 |
可以通过viper包 |
通过altsrc包实现 |
spf13/cobra
下载安装
1
|
$ go get -u github.com/spf13/cobra/cobra
|
在项目中使用引入
1
|
import "github.com/spf13/cobra"
|
Cobra 建立在commands, arguments & flags的结构之上。
commands代表动作,Args是事物,Flags是这些动作的修饰符。
cobra遵循的模式是 APPNAME VERB NOUN --ADJECTIVE.
or APPNAME COMMAND ARG --FLAG
Create rootCmd
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
var rootCmd = &cobra.Command{
Use: "hugo",
Short: "Hugo is a very fast static site generator",
Long: `A Fast and Flexible Static Site Generator built with
love by spf13 and friends in Go.
Complete documentation is available at http://hugo.spf13.com`,
Run: func(cmd *cobra.Command, args []string) {
// Do Stuff Here
},
}
func Execute() {
if err := rootCmd.Execute(); err != nil {
fmt.Println(err)
os.Exit(1)
}
}
|
添加子命令
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
|
package cmd
import (
"fmt"
"github.com/spf13/cobra"
)
func init() {
rootCmd.AddCommand(versionCmd)
}
var versionCmd = &cobra.Command{
Use: "version",
Short: "Print the version number of Hugo",
Long: `All software has versions. This is Hugo's`,
Run: func(cmd *cobra.Command, args []string) {
fmt.Println("Hugo Static Site Generator v0.9 -- HEAD")
},
}
|
添加命令就是在init函数中执行rootCmd.AddCommand.
cobra定义flag参数的方法
cobra用rootCmd.AddCommand添加子命令,在对应代码文件的init函数中定义flag.
支持全局参数和本地参数:
- newCmd.PersistentFlags。全局参数,根命令和子命令下都包含了这个参数项」。可以说定义一次,全局可用。
- newCmd.Flags。本地参数,只对当前命令下生效,其他子命令下不会继承。
提前定义存储变量:
1
2
|
var Verbose bool
var Source string
|
全局参数
1
|
rootCmd.PersistentFlags().BoolVarP(&Verbose, "verbose", "v", false, "verbose output")
|
本地参数
1
|
rootCmd.Flags().StringVarP(&Source, "source", "s", "", "Source directory to read from")
|
父命令上的本地参数
默认情况下,Cobra 仅解析目标命令上的本地标志,父命令上的任何本地标志都将被忽略。通过启用 Command.TraverseChildren
Cobra 将在执行目标命令之前解析每个命令上的本地标志。
1
2
3
4
|
command := cobra.Command{
Use: "print [OPTIONS] [COMMANDS]",
TraverseChildren: true,
}
|
绑定配置参数
使用viper绑定配置文件中的参数
1
2
3
4
5
6
|
var author string
func init() {
rootCmd.PersistentFlags().StringVar(&author, "author", "YOUR NAME", "Author name for copyright attribution")
viper.BindPFlag("author", rootCmd.PersistentFlags().Lookup("author"))
}
|
必须flags
默认情况下,flag是可选的。相反,如果您希望您的命令在未设置flag时报告错误,可以通过rootCmd.MarkFlagRequired
将其标记为必需:
1
2
|
rootCmd.Flags().StringVarP(&Region, "region", "r", "", "AWS region (required)")
rootCmd.MarkFlagRequired("region")
|
参数位置和自定义
- NoArgs: 如果包含任何位置参数,命令报错
- ArbitraryArgs: 命令接受任何参数
- OnlyValidArgs: 如果有位置参数不在ValidArgs中,命令报错
- MinimumArgs(init): 如果参数数目少于N个后,命令行报错
- MaximumArgs(init): 如果参数数目多余N个后,命令行报错
- ExactArgs(init): 如果参数数目不是N个话,命令行报错
- RangeArgs(min, max): 如果参数数目不在范围(min, max)中,命令行报错
Suggestions when “unknown command” happens
当发生 “unknown command” 错误时,会自动打印建议帮助.
1
2
3
4
5
6
7
|
$ hugo srever
Error: unknown command "srever" for "hugo"
Did you mean this?
server
Run 'hugo --help' for usage.
|
urfave/cli
下载安装
1
|
$ go get github.com/urfave/cli/v2
|
在项目中使用引入
1
|
import "github.com/urfave/cli/v2" // imports as package "cli"
|
定义和查询flag
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
|
package main
import (
"fmt"
"log"
"os"
"github.com/urfave/cli/v2"
)
func main() {
app := &cli.App{
Flags: []cli.Flag{
&cli.StringFlag{
Name: "lang",
Value: "english",
Usage: "language for the greeting",
},
},
Action: func(cCtx *cli.Context) error {
name := "Nefertiti"
if cCtx.NArg() > 0 {
name = cCtx.Args().Get(0)
}
if cCtx.String("lang") == "spanish" {
fmt.Println("Hola", name)
} else {
fmt.Println("Hello", name)
}
return nil
},
}
if err := app.Run(os.Args); err != nil {
log.Fatal(err)
}
}
|
设置别名和默认值
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
|
package main
import (
"log"
"os"
"github.com/urfave/cli/v2"
)
func main() {
app := &cli.App{
Flags: []cli.Flag{
&cli.StringFlag{
Name: "lang",
Aliases: []string{"l"},
Value: "english",
Usage: "language for the greeting",
},
},
}
if err := app.Run(os.Args); err != nil {
log.Fatal(err)
}
}
|
可以使用 --lang spanish
or -l spanish
设置环境变量
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
|
package main
import (
"log"
"os"
"github.com/urfave/cli/v2"
)
func main() {
app := &cli.App{
Flags: []cli.Flag{
&cli.StringFlag{
Name: "lang",
Aliases: []string{"l"},
Value: "english",
Usage: "language for the greeting",
EnvVars: []string{"LEGACY_COMPAT_LANG", "APP_LANG", "LANG"},
},
},
}
if err := app.Run(os.Args); err != nil {
log.Fatal(err)
}
}
|
可以通过EnvVars
设置多个环境变量值
从文件读取默认值
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
|
package main
import (
"log"
"os"
"github.com/urfave/cli/v2"
)
func main() {
app := &cli.App{
Flags: []cli.Flag{
&cli.StringFlag{
Name: "password",
Aliases: []string{"p"},
Usage: "password for the mysql database",
FilePath: "/etc/mysql/password",
},
},
}
if err := app.Run(os.Args); err != nil {
log.Fatal(err)
}
}
|
参考