简介
cli
是一个用于构建命令行程序的库。我们之前也介绍过一个用于构建命令行程序的库cobra
。在功能上来说两者差不多,cobra
的优势是提供了一个脚手架,方便开发。cli
非常简洁,所有的初始化操作就是创建一个cli.App
结构的对象。通过为对象的字段赋值来添加相应的功能。
cli
与我们上一篇文章介绍的negroni
是同一个作者urfave。
快速使用
cli
需要搭配 Go Modules 使用。创建目录并初始化:
$ mkdir cli && cd cli
$ go mod init github.com/darjun/go-daily-lib/cli
安装cli
库,有v1
和v2
两个版本。如果没有特殊需求,一般安装v2
版本:
$ go get -u github.com/urfave/cli/v2
使用:
package main
import (
"fmt"
"log"
"os"
"github.com/urfave/cli/v2"
)
func main() {
app := &cli.App{
Name: "hello",
Usage: "hello world example",
Action: func(c *cli.Context) error {
fmt.Println("hello world")
return nil
},
}
err := app.Run(os.Args)
if err != nil {
log.Fatal(err)
}
}
使用非常简单,理论上创建一个cli.App
结构的对象,然后调用其Run()
方法,传入命令行的参数即可。一个空白的cli
应用程序如下:
func main() {
(&cli.App{}).Run(os.Args)
}
但是这个空白程序没有什么用处。我们的hello world
程序,设置了Name/Usage/Action
。Name
和Usage
都显示在帮助中,Action
是调用该命令行程序时实际执行的函数,需要的信息可以从参数cli.Context
获取。
编译、运行(环境:Win10 + Git Bash):
$ go build -o hello
$ ./hello
hello world
除了这些,cli
为我们额外生成了帮助信息:
$ ./hello --help
NAME:
hello - hello world example
USAGE:
hello [global options] command [command options] [arguments...]
COMMANDS:
help, h Shows a list of commands or help for one command
GLOBAL OPTIONS:
--help, -h show help (default: false)
参数
通过cli.Context
的相关方法我们可以获取传给命令行的参数信息:
NArg()
:返回参数个数;Args()
:返回cli.Args
对象,调用其Get(i)
获取位置i
上的参数。
示例:
func main() {
app := &cli.App{
Name: "arguments",
Usage: "arguments example",
Action: func(c *cli.Context) error {
for i := 0; i < c.NArg(); i++ {
fmt.Printf("%d: %s\n", i+1, c.Args().Get(i))
}
return nil
},
}
err := app.Run(os.Args)
if err != nil {
log.Fatal(err)
}
}
这里只是简单输出:
$ go run main.go hello world
1: hello
2: world
选项
一个好用的命令行程序怎么会少了选项呢?cli
设置和获取选项非常简单。在cli.App{}
结构初始化时,设置字段Flags
即可添加选项。Flags
字段是[]cli.Flag
类型,cli.Flag
实际上是接口类型。cli
为常见类型都实现了对应的XxxFlag
,如BoolFlag/DurationFlag/StringFlag
等。它们有一些共用的字段,Name/Value/Usage
(名称/默认值/释义)。看示例:
func main() {
app := &cli.App{
Flags: []cli.Flag{
&cli.StringFlag{
Name: "lang",
Value: "english",
Usage: "language for the greeting",
},
},
Action: func(c *cli.Context) error {
name := "world"
if c.NArg() > 0 {
name = c.Args().Get(0)
}
if c.String("lang") == "english" {
fmt.Println("hello", name)
} else {
fmt.Println("你好", name)
}
return nil
},
}
err := app.Run(os.Args)
if err != nil {
log.Fatal(err)
}
}
上面是一个打招呼的命令行程序,可通过选项lang
指定语言,默认为英语。设置选项为非english
的值,使用汉语。如果有参数,使用第一个参数作为人名,否则使用world
。注意选项是通过c.Type(name)
来获取的,Type
为选项类型,name
为选项名。编译、运行:
$ go build -o flags
# 默认调用
$ ./flags
hello world
# 设置非英语
$ ./flags --lang chinese
你好 world
# 传入参数作为人名
$ ./flags --lang chinese dj
你好 dj
我们可以通过./flags --help
来查看选项:
$ ./flags --help
NAME:
flags - A new cli application
USAGE:
flag