Cobra 快速入門 - 專為命令行程序而生

作者:xcbeyond
瘋狂源自夢想,技術(shù)成就輝煌!微信公眾號:《程序猿技術(shù)大咖》號主,專注后端開發(fā)多年,擁有豐富的研發(fā)經(jīng)驗(yàn),樂于技術(shù)輸出、分享,現(xiàn)階段從事微服務(wù)架構(gòu)項(xiàng)目的研發(fā)工作,涉及架構(gòu)設(shè)計(jì)、技術(shù)選型、業(yè)務(wù)研發(fā)等工作。對于Java、微服務(wù)、數(shù)據(jù)庫、Docker有深入了解,并有大量的調(diào)優(yōu)經(jīng)驗(yàn)。 








最近一直在看 Istio(一個(gè) Service Mesh 框架)相關(guān)的東西,當(dāng)看到其源碼時(shí)發(fā)現(xiàn)了一個(gè)新東西 Cobra,一查卻發(fā)現(xiàn)這是個(gè)好東西,用的地方可不少,比如:Docker、Kubernetes 等都有它的身影存在。為了更好的了解這些開源框架(如,Istio、Kubernetes 等),勢必需要對 Cobra 做一個(gè)詳細(xì)的了解,后續(xù)可能用到它的地方會(huì)很多。今天就 Cobra 做一個(gè)整體的介紹,讓我們對它能有所認(rèn)識(shí),或許今后你的項(xiàng)目中也會(huì)用到它。
1、Cobra 介紹
1.1 Cobra 概述

Cobra 是一個(gè) Golang 包,它提供了簡單的接口來創(chuàng)建命令行程序。同時(shí),Cobra 也是一個(gè)應(yīng)用程序,用來生成應(yīng)用框架,從而開發(fā)以 Cobra 為基礎(chǔ)的應(yīng)用。

Cobra
1.2 主要功能

Cobra 的主要功能如下:

    簡易的子命令行模式,如 app server, app fetch 等等。
    完全兼容 posix 命令行模式。
    嵌套子命令 subcommand。
    支持全局,局部,串聯(lián) flags。
    使用 cobra 很容易生成應(yīng)用程序和命令(cobra init appname 和 cobra add cmdname)。
    提供智能化的提示(如,輸出 app srver 命令,將提示 你是要輸入 app server 嗎?)。
    自動(dòng)生成 commands 和 flags 的幫助信息。
    自動(dòng)生成詳細(xì)的 help 信息,如 app -help。
    自動(dòng)識(shí)別幫助 flag、 -h,--help。
    自動(dòng)生成應(yīng)用程序在 bash 下命令自動(dòng)完成功能。
    自動(dòng)生成應(yīng)用程序的 man 手冊。
    命令行別名。
    自定義 help 和 usage 信息。
    可選的與 viper 的緊密集成。

對于命令行程序而言,上面這些功能簡直就是量身打造。
1.3 應(yīng)用舉例

Cobra 被用于許多 Go 項(xiàng)目中,例如:Kubernetes、Hugo和Github CLI等,更多廣泛使用的項(xiàng)目有:

(來源于:https://github.com/spf13/cobra/blob/master/projects_using_cobra.md)

    Arduino CLI
    Bleve
    CockroachDB
    Cosmos SDK
    Delve
    Docker (distribution)
    Etcd
    Gardener
    Giant Swarm’s gsctl
    Git Bump
    Github CLI
    GitHub Labeler
    Golangci-lint
    GopherJS
    Helm
    Hugo
    Istio
    Kool
    Kubernetes
    Linkerd
    Mattermost-server
    Metal Stack CLI
    Moby (former Docker)
    Nanobox/Nanopack
    OpenShift
    Ory Hydra
    Ory Kratos
    Pouch
    ProjectAtomic (enterprise)
    Prototool
    Random
    Rclone
    Skaffold
    Tendermint
    Twitch CLI
    Werf

看了這些,一個(gè)字“贊”,兩個(gè)字“優(yōu)秀”!

了解了 Cobra 后,再去看這些 Kubernetes、etcd、Registry 等開源項(xiàng)目的代碼時(shí),也就大概知道如何去看了,這也就是我學(xué)習(xí) Cobra 的目的。
2、概念

Cobra 是基于命令(commands)、參數(shù)(arguments )、選項(xiàng)(flags)而創(chuàng)建的。

在具體了解、使用Cobra前有一些概念需要提前知曉一下:命令(commands)、參數(shù)(arguments )、選項(xiàng)(flags)這幾個(gè)概念。

    commands:命令代表行為,一般表示 action,即運(yùn)行的二進(jìn)制命令服務(wù)。同時(shí)可以擁有子命令(children commands)
    arguments:參數(shù)代表命令行參數(shù)。
    flags:選項(xiàng)代表對命令行為的改變,即命令行選項(xiàng)。二進(jìn)制命令的配置參數(shù),可對應(yīng)配置文件。參數(shù)可分為全局參數(shù)和子命令參數(shù)。

最好的命令行程序在實(shí)際使用時(shí),就應(yīng)該像在讀一段優(yōu)美的語句,能夠更加直觀的知道如何與用戶進(jìn)行交互。執(zhí)行命令行程序應(yīng)該遵循一般的格式: APPNAME VERB NOUN --ADJECTIVE 或 APPNAME COMMAND ARG --FLAG。

比如下面的示例:

    # server是 commands,port 是 flag
    hugo server --port=1313
     
    # clone 是 commands,URL 是 arguments,brae 是 flag
    git clone URL --bare

再比如:

    xcbeyond@xcbeyonddeMacBook-Pro ~ % docker info --help
     
    Usage:  docker info [OPTIONS]
     
    Display system-wide information
     
    Options:
      -f, --format string   Format the output using the given Go template

你沒有看錯(cuò),像 Docker 這種這么復(fù)雜的命令都是用 Cobra 是實(shí)現(xiàn)的,其必有過人之處,下一節(jié)就讓我們一起來看看如何實(shí)現(xiàn)一套屬于自己的命令行工具吧!
3、Cobra 實(shí)戰(zhàn)

實(shí)戰(zhàn)是最好的學(xué)習(xí)方式! 本節(jié)將從一個(gè)實(shí)戰(zhàn)帶你快速入門 Cobra。
3.1 環(huán)境準(zhǔn)備

3.1.1 前提條件&環(huán)境

    操作系統(tǒng):MacOS
    Go 環(huán)境:go 1.16
    Go 開發(fā) IDE:VSCode

(上述環(huán)境可以個(gè)人環(huán)境而定,不做限制)






3.1.2 Cobra 安裝

使用 go get 命令獲取最新版本的 Cobra 庫。下面命令將會(huì)安裝 Cobra 及其相關(guān)依賴包:

go get -u github.com/spf13/cobra/cobra

下載安裝完 Cobra 后,打開 GOPATH 目錄,在 bin 目錄下會(huì)下載好 cobra 程序(Window: cobra.exe, MacOS: cobra)。

3.1.3 工程初始化(Cobra 代碼生成器)

假設(shè)現(xiàn)需要開發(fā)一個(gè)基于 Cobra 的 CLI 的命令行程序,命名為 cobra-demo。

由于 Cobra 提供了代碼生成器的功能,我們可以直接使用 Cobra 提供的初始化命令 cobra init 進(jìn)行快速初始化創(chuàng)建 Cobra 工程。

切換到 GOPATH 目錄(如,/Users/xcbeyond/github),執(zhí)行命令 cobra init <name> --pkg-name <pkgname>,如下:

    xcbeyond@xcbeyonddeMacBook-Pro github % .\bin\cobra init cobra-demo --pkg-name github.com/xcbeyond/cobra-demo
    Your Cobra application is ready at
    /Users/xcbeyond/github/cobra-demo

初始化成功后,cobra-demo 程序目錄結(jié)構(gòu)如下:

    .
    ├── cmd
    │   ├── root.go
    │   └── show.go
    ├── go.mod
    ├── go.sum
    └── main.go

3.1.4 運(yùn)行

執(zhí)行命令 go run 運(yùn)行:

    xcbeyond@xcbeyonddeMacBook-Pro cobra-demo % go run main.go
    A longer description that spans multiple lines and likely contains
    examples and usage of using your application. For example:
     
    Cobra is a CLI library for Go that empowers applications.
    This application is a tool to generate the needed files
    to quickly create a Cobra application.

3.2 實(shí)戰(zhàn)

這里以一個(gè)簡單的 time 命令為例,實(shí)戰(zhàn)講解如何 Cobra 開發(fā)一個(gè)命令。

功能如下:

    show:查看當(dāng)前時(shí)間。
    parse:指定時(shí)間格式 –format,parse 為 show 的子命令。

3.2.1 實(shí)現(xiàn) show 命令(Command命令)

    添加 show 命令

    通過命令 cobra add 添加 show 命令:

        xcbeyond@xcbeyonddeMacBook-Pro cobra-demo % ../bin/cobra add show
        show created at /Users/xcbeyond/github/cobra-demo

    此時(shí),項(xiàng)目目錄下會(huì)創(chuàng)建一個(gè) show.go 文件,在該文件中可完成命令的具體操作邏輯。

    下面是 show.go 文件的初始代碼:

        // showCmd represents the show command
        var showCmd = &cobra.Command{
            Use:   "show",
            Short: "A brief description of your command",
            Long: `A longer description that spans multiple lines and likely contains examples
        and usage of using your command. For example:
         
        Cobra is a CLI library for Go that empowers applications.
        This application is a tool to generate the needed files
        to quickly create a Cobra application.`,
            Run: func(cmd *cobra.Command, args []string) {
                fmt.Println("show called")
            },
        }
         
        func init() {
            rootCmd.AddCommand(showCmd)
         
            // Here you will define your flags and configuration settings.
         
            // Cobra supports Persistent Flags which will work for this command
            // and all subcommands, e.g.:
            // showCmd.PersistentFlags().String("foo", "", "A help for foo")
         
            // Cobra supports local flags which will only run when this command
            // is called directly, e.g.:
            // showCmd.Flags().BoolP("toggle", "t", false, "Help message for toggle")
        }

    &cobra.Command 作為命令的定義,其中有如下變量:
        Use:用于指定具體的命令,如:show。
        Short:命令的簡短描述。
        Long:命令的詳細(xì)描述。
        Run:命令執(zhí)行入口,用于實(shí)現(xiàn)命令的具體處理邏輯。

    rootCmd.AddCommand(showCmd) 命令的添加,將命令添加到根命令。(Cobra 支持命令的子命令)

    實(shí)現(xiàn)顯示當(dāng)前時(shí)間邏輯

    在 &cobra.Command.Run 中添加獲取當(dāng)前時(shí)間邏輯 time.Now():

        var showCmd = &cobra.Command{
            Use:   "show",
            Short: "A brief description of your command",
            Long: `A longer description that spans multiple lines and likely contains examples
        and usage of using your command. For example:
         
        Cobra is a CLI library for Go that empowers applications.
        This application is a tool to generate the needed files
        to quickly create a Cobra application.`,
            Run: func(cmd *cobra.Command, args []string) {
                // show current time
                fmt.Println(time.Now())
            },
        }

    修改 help 命令

    help 命令有兩個(gè),一個(gè)是 short,一個(gè)是 lang,很明顯 short 命令用來定義簡短的說明,lang 命令用來定義詳細(xì)說明,下面我們修改 show 命令的 help:

        var showCmd = &cobra.Command{
            Use:   "show",
            Short: "Displays the current time",
            Long: `You can use the time show command to view the current time. For example:
        $ ./cobra-demo show
        2021-03-19 14:34:20.9320241 +0800 CST m=+0.378845301`,
            Run: func(cmd *cobra.Command, args []string) {
                // show current time
                fmt.Println(time.Now())
            },
        }

    運(yùn)行

    執(zhí)行 show 命令:

        xcbeyond@xcbeyonddeMacBook-Pro cobra-demo % go run main.go show
        2021-07-31 14:49:27.3582836 +0800 CST m=+0.176660901

    執(zhí)行 show –help 命令:

        xcbeyond@xcbeyonddeMacBook-Pro cobra-demo % go run main.go show --help
        You can use the time show command to view the current time. For example:
         
        $ ./cobra-demo show
        2021-07-31 14:34:20.9320241 +0800 CST m=+0.378845301
         
        Usage:
        cobra-demo show [flags]
         
        Flags:
        -h, --help   help for show
         
        Global Flags:
                --config string   config file (default is $HOME/.cobra-demo.yaml)

4、總結(jié)

Cobra-demo 只是簡單的闡述了由幾部分組成,在實(shí)際項(xiàng)目中要比這復(fù)雜的很多,一般都是擁有多個(gè)子命令,但核心內(nèi)容都是類似的。