![Go-brown-side.sh]()
如果你要寫 Command line 工具,又想在各平台 (像是 MacOS, Windows 或 Linux) 上執行,這時候
Golang 就是您最好的選擇。在
Reddit 讀到一篇
Command line 工具比較介紹,這篇最主要講到兩個 CLI 工具,一個是
urfave/cli,另一個是
spf13/cobra,這兩個工具其實都非常好用,後者是
去年加入 Google Golang 團隊的
spf13 所開發,該作者加入 Google 後呢,非常的忙,但是強者他同事有幫忙繼續維護 cobra 專案,兩個 CLI 工具各自都有有大型專案使用 urfave/cli 有
docker/libcompose,
docker/machine,
Drone,
Gitea,
Gogs 等,而後者 spf13/cobra 則有
docker,
docker/distribution,
etcd 等。本篇筆者會介紹 urfave/cli 該如何使用?
用 Golang 內建 flag 套件
其實 Golang 本身就有支援 Command line 功能,只要 import
flag
就可以直接使用了
package main
import (
"flag"
"fmt"
"os"
)
func main() {
var showVersion bool
flag.BoolVar(&showVersion, "version", false, "Print version information.")
flag.BoolVar(&showVersion, "v", false, "Print version information.")
flag.Parse()
// Show version and exit
if showVersion {
fmt.Println("Version 1.0.0")
os.Exit(0)
}
}
存檔成
main.go
,執行
go build -o main
就可以產生 main 執行檔,最後可以直接下
./main -v
畫面就會顯示
Version 1.0.0
。但是如果 flag 非常多,寫起來就會相當長,也不支援讀取 Environment 環境變數,這時候我們可以透過 urfave/cli 來簡化此流程。上面的範例可以在底下連結找到
使用 urfave/cli 套件
底下是一個簡單範例,可以從 command line 讀取使用者帳號密碼
package main
import (
"fmt"
"os"
"github.com/urfave/cli"
)
type (
// Config information.
Config struct {
username string
password string
}
)
var config Config
func main() {
app := cli.NewApp()
app.Name = "Example"
app.Usage = "Example"
app.Action = run
app.Flags = []cli.Flag{
cli.StringFlag{
Name: "username,u",
Usage: "user account",
},
cli.StringFlag{
Name: "password,p",
Usage: "user password",
},
}
app.Run(os.Args)
}
func run(c *cli.Context) error {
config = Config{
username: c.String("username"),
password: c.String("password"),
}
return exec()
}
func exec() error {
fmt.Println("username:", config.username)
fmt.Println("password:", config.password)
return nil
}
從上面例子可以發現從
Name
就可以定義 Flag 名稱,用逗號分格,在命令列就可以使用
-u
或
--username
,也會自動幫忙產生完整的 help 畫面
支援環境變數
在 Golang 可以快速的將執行檔打包成
Docker Image
FROM centurylink/ca-certs
ADD main /
ENTRYPOINT ["/main"]
在 Dockerfile 內使用參數可以透過
CMD
會變成底下
FROM centurylink/ca-certs
ADD main /
ENTRYPOINT ["/main"]
CMD ["-u", "appleboy"]
這樣非常麻煩,這時候就要讓 CLI 也支援環境變數,將
cli.StringFlag
改成如下
app.Flags = []cli.Flag{
cli.StringFlag{
Name: "username,u",
Usage: "user account",
+ EnvVar: "DOCKER_USERNAME",
},
cli.StringFlag{
Name: "password,p",
Usage: "user password",
+ EnvVar: "DOCKER_PASSWORD",
},
}
直接在命令列執行
DOCKER_USERNAME=appleboy ./main
,則就會抓到
DOCKER_USERNAME
環境變數,在 Docker 指令就可以補上
-e
參數來實現變數傳遞:
$ docker run -e DOCKER_USERNAME=appleboy appleboy/cli
結論
把 Golang 執行檔包進去 Docker Image,就可以再任意環境內執行,如果你不想使用 Docker Image 也沒關係,Golang 支援跨平台編譯,底下是支援 Windows, Linux, MacOS 編譯參數
GOOS=linux GOARCH=amd64 CGO_ENABLED=0 go build -o bin/main-linux
GOOS=windows GOARCH=amd64 CGO_ENABLED=0 go build -o bin/main.exe
GOOS=darwin GOARCH=amd64 CGO_ENABLED=0 go build -o bin/main-darwin
自從學了 Golang,讓用 Windows 工作的同事,也可以享用 Golang 的好處。上述範例檔案可以參考底下連結