今天我們繼續(xù)講解Go語言中命令行罐栈,當我們在解析命令行傳遞的參數(shù)時通常會想用最簡單的方法來解析自己行用到的命令行參數(shù)痕支,那么urfave/cli可以幫助我們快速的解析命令行參數(shù)雳攘,它是一個簡單快速的命令行包汛兜,用于在Go語言中構建命令行應用程序颠焦,目的是使開發(fā)人員能夠以表達的方式編寫快速分發(fā)的命令行應用程序,urfave/cli庫抽象出來:Flag里逆、Command,SubCommand等模塊进胯,用戶只需要設置模塊信息,參數(shù)的解析和關聯(lián)就可以原押,幫助信息自動生成胁镐。
在C語言中可以通過getopt(int argc, char * const argv[], const char *optstring)來完成參數(shù)解析,這里不做示例诸衔,有興趣的同學可以自己動手嘗試一下盯漂。
安裝urfave/cli:
go get github.com/urfave/cli
包引用方法:
import "github.com/urfave/cli" //引入cli包
urfave/cli包中幾個重要的方法:
cli.NewApp() // 創(chuàng)建一個cli實例
Run() // 程序入口,執(zhí)行Run后分析參數(shù)切片和路由
app.Commands // 要執(zhí)行的命令列表
app.Before // 運行命令之前執(zhí)行的內容
app.After // 運行命令之后執(zhí)行的內容
Subcommands // 子命令
好笨农,開始我們演示就缆,今天的演示示例有點長,項目目錄結構如下:
#tree
.
|-- commands
| |-- api
| | `-- api.go // api commands
| `-- service
| `-- service.go // 服務 commands
|-- go_cli.go // main入口
|-- go.mod // go module管理包
|-- go.sum
`-- webservice
|-- bin
| `-- webservice
`-- webservice.go // web服務類
首先谒亦,定義webservice類:
webservice類主要完成幾個功能:構造函數(shù)竭宰,釋放資源函數(shù),ApiService方法和Service方法份招。
package webservice
import "fmt"
// web service 類
type WebService struct {
Config string
Port int
LogFile string
}
// 返回web service 實例
func NewWebService(config, logFile string, port int) *WebService {
var ws = &WebService{
Port: port,
Config: config,
LogFile: logFile,
}
return ws
}
// 釋放資源
func (ws *WebService) Freed() {
}
// API調用啟動方式
func (ws *WebService) ApiService() {
fmt.Println("api service")
fmt.Printf("port : %d \n", ws.Port)
fmt.Printf("config : %s \n", ws.Config)
fmt.Printf("logfile : %s \n", ws.LogFile)
// 啟動http服務
}
// 常駐方式啟動
func (ws *WebService) Service() {
fmt.Println("service")
fmt.Printf("config : %s \n", ws.Config)
fmt.Printf("logfile : %s \n", ws.LogFile)
// 可以理解成類似Nginx這類服務的啟動
}
我們創(chuàng)建Api和Service兩個Commands的目錄切揭,用于分開執(zhí)行HTTPService和Service兩種模式。
ApiService:
在日常工作中脾还,HTTP-Api的試比較常見的獲取數(shù)據(jù)的方式伴箩,我們用這個例子來看看在命令行里面如何啟動和傳遞參數(shù)的。
package api
import (
"fmt"
"github.com/gzh/webservice"
"github.com/urfave/cli"
"os"
)
var Command = cli.Command{
Name: "api",
Aliases: []string{"web_api", "webApi"}, // 命令別名
Flags: []cli.Flag{
// int型參數(shù)port鄙漏,value默認是8080
cli.IntFlag{
Name: "port",
Value: 8080,
Usage: "/usr/local/web_service/service api --port=8080",
},
// 字符型參數(shù)配置文件嗤谚,默認值為空
cli.StringFlag{
Name: "config",
Value: "",
Usage: "/usr/local/web_service/service api --config=/usr/local/web_service/config",
},
// 字符型日志文件參數(shù),默認值為空
cli.StringFlag{
Name: "log_file",
Value: "",
Usage: "/usr/local/web_service/service api --log_file=/usr/local/web_service/log/web_service.log",
},
},
Action: func(c *cli.Context) error {
var port = c.Int("port") // 從上下文中獲取端口
var config = c.String("config") // 從上下文中獲取配置文件
var logFile = c.String("log_file") // 從上下文中獲取日志文件
if config == "" {
_, _ = fmt.Fprintf(os.Stderr, "config is empty!\n")
os.Exit(100001) // 配置文件錯誤碼
}
if port <= 0 {
_, _ = fmt.Fprintf(os.Stderr, "port is empty!\n")
os.Exit(100002) // 端口錯誤碼
}
if logFile == "" {
_, _ = fmt.Fprintf(os.Stderr, "log_file is empty!\n")
os.Exit(100003) // 日志文件錯誤碼
}
// 實例webservice怔蚌,構造函數(shù)參數(shù):config巩步,logfile,port
var api = webservice.NewWebService(config, logFile, port)
defer api.Freed()
// 啟動HTTP-API服務
api.ApiService()
return nil
},
}
Service:
Service類似于Nginx一樣桦踊,啟動后常駐執(zhí)行的服務椅野,這種在后端中比較多見,下面的示例為Service的啟動和傳遞參數(shù)方式。
package service
import (
"fmt"
"github.com/gzh/webservice"
"github.com/urfave/cli"
"os"
)
var Command = cli.Command{
Name: "service",
Flags: []cli.Flag{
// 字符型參數(shù)配置竟闪,默認值為空
cli.StringFlag{
Name: "config",
Value: "",
Usage: "/usr/local/web_service/service api --config=/usr/local/web_service/config",
},
// 字符型日志文件參數(shù)离福,默認值為空
cli.StringFlag{
Name: "log_file",
Value: "",
Usage: "/usr/local/web_service/service api --log_file=/usr/local/web_service/log/web_service.log",
},
},
Action: func(c *cli.Context) error {
var config = c.String("config") // 從上下文中獲取配置文件
var logFile = c.String("log_file") // 從上下文中獲取日志文件
if config == "" {
_, _ = fmt.Fprintf(os.Stderr, "config is empty!\n")
os.Exit(100001) // 配置文件錯誤碼
}
if logFile == "" {
_, _ = fmt.Fprintf(os.Stderr, "log_file is empty!\n")
os.Exit(100003) // 日志文件錯誤碼
}
// 實例webservice,構造函數(shù)參數(shù):config炼蛤,logfile
var api = webservice.NewWebService(config, logFile, 0)
defer api.Freed()
// 啟動服務
api.Service()
return nil
},
}
完成上面的幾個類之后妖爷,我們可以創(chuàng)建go_cli.go文件開始我們的編碼。主要是實現(xiàn)main函數(shù)理朋,里面創(chuàng)建cli實例絮识,配置參數(shù)解析相關信息、版本嗽上、描述和幫助等信息次舌。
package main
import (
"fmt"
"github.com/gzh/commands/api"
"github.com/gzh/commands/service"
"github.com/urfave/cli"
"os"
)
func main() {
// 實例化命令行
app := cli.NewApp()
// 服務的名稱
app.Name = "WebService"
// 服務的描述
app.Description = "Web服務相關描述"
// 服務的用途描述
app.Usage = "webservice api --port=8080 --config=path --log_file=/usr/local/webservice/log/go_cli.log"
// 服務的版本號信息
app.Version = "1.0.0"
// 初始化多個命令
app.Commands = []cli.Command{
// api命令
api.Command,
// service命令
service.Command,
}
app.Before = func(context *cli.Context) error {
// 實現(xiàn)一些邏輯
return nil
}
app.After = func(context *cli.Context) error {
// 實現(xiàn)一些邏輯
return nil
}
var err = app.Run(os.Args)
if err != nil {
fmt.Println("app run fatal! err : ", err)
}
}
運行結果:
1、編譯運行Api示例:
#go build -o webservice/bin/webservice go_cli.go
#./webservice/bin/webservice api -port=8080 -config=path -log_file=/usr/local/webservice/log/go_cli.log
api service
port : 8080
config : path
logfile : /usr/local/webservice/log/go_cli.log
2兽愤、編譯運行Service示例:
#go build -o webservice/bin/webservice go_cli.go
#./webservice/bin/webservice service -config=path -log_file=/usr/local/webservice/log/go_cli.log
service
config : path
logfile : /usr/local/webservice/log/go_cli.log
3彼念、不傳遞任何參數(shù)的時候,會提示命令會出現(xiàn)HELP信息浅萧,運行如下国拇。
#go build -o webservice/bin/webservice go_cli.go
#./webservice/bin/webservice
NAME:
WebService - webservice api --port=8080 --config=path --log_file=/usr/local/webservice/log/go_cli.log
USAGE:
go_cli.exe [global options] command [command options] [arguments...]
VERSION:
1.0.0
DESCRIPTION:
Web服務相關描述
COMMANDS:
api
service
help, h Shows a list of commands or help for one command
GLOBAL OPTIONS:
--help, -h show help
--version, -v print the version
總結:
命令行解析上支持的比較友好,支持的內容比較全面
使用上方便惯殊,快速