Go语言命令行库urfave/cli简介
很多用Go寫的命令行程序都用了urfave/cli這個庫,包括geth,有必要簡單了解一下。
用C寫過命令行程序的人應該都不陌生,我們需要根據argc/argv一個個地解析命令行參數,調用不同的函數,最后還要寫一個usage()函數用于打印幫助信息。urfave/cli把這個過程做了一下封裝,抽象出flag/command/subcommand這些模塊,用戶只需要提供一些模塊的配置,參數的解析和關聯在庫內部完成,幫助信息也可以自動生成。
舉個例子,我們想要實現下面這個命令行程序:
NAME:GoTest - hello worldUSAGE:GoTest [global options] command [command options] [arguments...]VERSION:1.2.3COMMANDS:help, h ?Shows a list of commands or help for one commandarithmetic:add, a ?calc 1+1sub, s ?calc 5-3database:db ?database operationsGLOBAL OPTIONS:--lang FILE, -l FILE ? ?read from FILE (default: "english")--port value, -p value ?listening port (default: 8000)--help, -h ? ? ? ? ? ? ?Help!Help!--print-version, -v ? ? print version
1. 基本結構
導入包以后,通過cli.NewApp()創建一個實例,然后調用Run()方法就實現了一個最基本的命令行程序了。
當然,為了讓我們的程序干點事情,可以指定一下入口函數app.Action,具體寫法如下:
?import ("fmt""gopkg.in/urfave/cli.v1" )func main() {app := cli.NewApp()app.Action = func(c *cli.Context) error {fmt.Println("BOOM!")return nil}err := app.Run(os.Args)if err != nil {log.Fatal(err)} }
2. 公共配置
就是幫助里需要顯示的一些基本信息:
??
?app.Name = "GoTest"app.Usage = "hello world"app.Version = "1.2.3"
3. Flag配置
具體對應于幫助中的以下信息:
? ?
--lang FILE, -l FILE ? ?read from FILE (default: "english") --port value, -p value ?listening port (default: 8000)
對應代碼:
?? ?
var language stringapp.Flags = []cli.Flag {cli.IntFlag {Name: "port, p",Value: 8000,Usage: "listening port",},cli.StringFlag {Name: "lang, l",Value: "english",Usage: "read from `FILE`",Destination: &language,},}
可以看到,每一個flag都對應一個cli.Flag接口的實例。
Name字段中逗號后面的字符表示flag的簡寫,也就是說"--port"和"-p"是等價的。
Value字段可以指定flag的默認值。
Usage字段是flag的描述信息。
Destination字段可以為該flag指定一個接收者,比如上面的language變量。解析完"--lang"這個flag后會自動存儲到這個變量里,后面的代碼就可以直接使用這個變量的值了。
另外,如果你想給用戶增加一些屬性值類型的提示,可以通過占位符(placeholder)來實現,比如上面的"--lang FILE"。占位符通過``符號來標識。
我們可以在app.Action中測試一下打印這些flag的值:
?? ?
app.Action = func(c *cli.Context) error {fmt.Println("BOOM!")fmt.Println(c.String("lang"), c.Int("port"))fmt.Println(language)return nil}
另外,正常來說幫助信息里的flag是按照代碼里的聲明順序排列的,如果你想讓它們按照字典序排列的話,可以借助于sort:
最后,help和version這兩個flag有默認實現,也可以自己改:
?cli.HelpFlag = cli.BoolFlag {Name: "help, h",Usage: "Help!Help!",}cli.VersionFlag = cli.BoolFlag {Name: "print-version, v",Usage: "print version",}
4. Command配置
命令行程序除了有flag,還有command(比如git log, git commit等等)。
另外每個command可能還有subcommand,也就必須要通過添加兩個命令行參數才能完成相應的操作。比如我們的db命令包含2個子命令,如果輸入GoTest db -h會顯示下面的信息:
NAME:GoTest db - database operationsUSAGE:GoTest db command [command options] [arguments...]COMMANDS:insert ?insert datadelete ?delete dataOPTIONS:--help, -h ?Help!Help!
每個command都對應于一個cli.Command接口的實例,入口函數通過Action指定。如果你想像在幫助信息里實現分組顯示,可以為每個command指定一個Category。具體代碼如下:
如果你想在command執行前后執行后完成一些操作,可以指定app.Before/app.After這兩個字段:
具體測試一下:
5. 小結
總體來說,urfave/cli這個庫還是很好用的,完成了很多routine的工作,程序員只需要專注于具體業務邏輯的實現。
附完整demo代碼:
package cliimport ("fmt""os""log""sort""gopkg.in/urfave/cli.v1" )func Run() {var language stringapp := cli.NewApp()app.Name = "GoTest"app.Usage = "hello world"app.Version = "1.2.3"app.Flags = []cli.Flag {cli.IntFlag {Name: "port, p",Value: 8000,Usage: "listening port",},cli.StringFlag {Name: "lang, l",Value: "english",Usage: "read from `FILE`",Destination: &language,},}app.Commands = []cli.Command {{Name: "add",Aliases: []string{"a"},Usage: "calc 1+1",Category: "arithmetic",Action: func(c *cli.Context) error {fmt.Println("1 + 1 = ", 1 + 1)return nil},},{Name: "sub",Aliases: []string{"s"},Usage: "calc 5-3",Category: "arithmetic",Action: func(c *cli.Context) error {fmt.Println("5 - 3 = ", 5 - 3)return nil},},{Name: "db",Usage: "database operations",Category: "database",Subcommands: []cli.Command {{Name: "insert",Usage: "insert data",Action: func(c *cli.Context) error {fmt.Println("insert subcommand")return nil},},{Name: "delete",Usage: "delete data",Action: func(c *cli.Context) error {fmt.Println("delete subcommand")return nil},},},},}app.Action = func(c *cli.Context) error {fmt.Println("BOOM!")fmt.Println(c.String("lang"), c.Int("port"))fmt.Println(language)// if c.Int("port") == 8000 {// ?? ?return cli.NewExitError("invalid port", 88)// }return nil}app.Before = func(c *cli.Context) error {fmt.Println("app Before")return nil}app.After = func(c *cli.Context) error {fmt.Println("app After")return nil}sort.Sort(cli.FlagsByName(app.Flags))cli.HelpFlag = cli.BoolFlag {Name: "help, h",Usage: "Help!Help!",}cli.VersionFlag = cli.BoolFlag {Name: "print-version, v",Usage: "print version",}err := app.Run(os.Args)if err != nil {log.Fatal(err)} }
---------------------?
作者:turkeycock?
來源:CSDN?
原文:https://blog.csdn.net/TurkeyCock/article/details/80359654?
版權聲明:本文為博主原創文章,轉載請附上博文鏈接!
總結
以上是生活随笔為你收集整理的Go语言命令行库urfave/cli简介的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: JavaWeb-Spring中注解大全与
- 下一篇: 消息中间件选型分析 —— 从 Kafka