《Go語言四十二章經(jīng)》第三十四章 命令行flag包

《Go語言四十二章經(jīng)》第三十四章 命令行 flag 包

作者:李驍

34.1 命令行

寫命令行程序時需要對命令參數(shù)進(jìn)行解析,這時我們可以使用os庫孙蒙。os庫可以通過變量Args來獲取命令參數(shù)斋射,os.Args返回一個字符串?dāng)?shù)組禾进,其中第一個參數(shù)就是執(zhí)行文件本身硬鞍。

package main
 
import (
    "fmt"
    "os"
)
 
func main() {
    fmt.Println(os.Args)
}

編譯執(zhí)行后執(zhí)行

$ ./cmd -user="root"
 [./cmd -user=root]

這種方式對于簡單的參數(shù)格式還能使用呼奢,一旦面對復(fù)雜的參數(shù)格式化戳,比較費時費勁单料,所以這時我們會選擇flag庫。

34.2 flag包

Go提供了flag包点楼,可以很方便的操作命名行參數(shù)扫尖,下面介紹下flag的用法。

幾個概念:

1)命令行參數(shù)(或參數(shù)):是指運(yùn)行程序提供的參數(shù)

2)已定義命令行參數(shù):是指程序中通過flag.Xxx等這種形式定義了的參數(shù)

3)非flag(non-flag)命令行參數(shù)(或保留的命令行參數(shù)):先可以簡單理解為flag包不能解析的參數(shù)

package main

import (
    "flag"
    "fmt"
    "os"
)

var (
    h, H bool

    v bool
    q *bool

    D    string
    Conf string
)

func init() {
    flag.BoolVar(&h, "h", false, "幫助信息")
    flag.BoolVar(&h, "H", false, "幫助信息")

    flag.BoolVar(&v, "v", false, "顯示版本號")

    //
    flag.StringVar(&D, "D", "deamon", "set descripton ")
    flag.StringVar(&Conf, "Conf", "/dev/conf/cli.conf", "set Conf filename ")

    // 另一種綁定方式
    q = flag.Bool("q", false, "退出程序")

    // 像flag.Xxx函數(shù)格式都是一樣的掠廓,第一個參數(shù)表示參數(shù)名稱换怖,
    // 第二個參數(shù)表示默認(rèn)值,第三個參數(shù)表示使用說明和描述蟀瞧。
    // flag.XxxVar這樣的函數(shù)第一個參數(shù)換成了變量地址狰域,
        // 后面的參數(shù)和flag.Xxx是一樣的。

    // 改變默認(rèn)的 Usage

    flag.Usage = usage

    flag.Parse()

    var cmd string = flag.Arg(0)

    fmt.Printf("-----------------------\n")
    fmt.Printf("cli non=flags      : %s\n", cmd)

    fmt.Printf("q: %b\n", *q)

    fmt.Printf("descripton:  %s\n", D)
    fmt.Printf("Conf filename : %s\n", Conf)

    fmt.Printf("-----------------------\n")
    fmt.Printf("there are %d non-flag input param\n", flag.NArg())
    for i, param := range flag.Args() {
        fmt.Printf("#%d    :%s\n", i, param)
    }

}

func main() {
    flag.Parse()

    if h || H {
        flag.Usage()
    }
}

func usage() {
    fmt.Fprintf(os.Stderr, `CLI: 8.0
Usage: Cli [-hvq] [-D descripton] [-Conf filename] 

`)
    flag.PrintDefaults()
}

flag包實現(xiàn)了命令行參數(shù)的解析黄橘,大致需要幾個步驟:

一:flag參數(shù)定義或綁定

定義flags有兩種方式:

1)flag.Xxx()兆览,其中Xxx可以是Int、String等塞关;返回一個相應(yīng)類型的指針抬探,如:

var ip = flag.Int("flagname", 1234, "help message for flagname")

2)flag.XxxVar(),將flag綁定到一個變量上帆赢,如:

var flagvar int
flag.IntVar(&flagvar, "flagname", 1234, "help message for flagname")

另外小压,還可以創(chuàng)建自定義flag,只要實現(xiàn)flag.Value接口即可(要求receiver是指針)椰于,這時候可以通過如下方式定義該flag:

flag.Var(&flagVal, "name", "help message for flagname")

命令行flag的語法有如下三種形式:
-flag // 只支持bool類型
-flag=x
-flag x // 只支持非bool類型

二:flag參數(shù)解析

在所有的flag定義完成之后怠益,可以通過調(diào)用flag.Parse()進(jìn)行解析。

根據(jù)Parse()中for循環(huán)終止的條件瘾婿,當(dāng)parseOne返回false蜻牢,nil時烤咧,Parse解析終止。

s := f.args[0]
if len(s) == 0 || s[0] != '-' || len(s) == 1 {
    return false, nil
}

當(dāng)遇到單獨的一個“-”或不是“-”開始時抢呆,會停止解析煮嫌。比如:./cli – -f 或 ./cli -f

這兩種情況,-f都不會被正確解析抱虐。像這些參數(shù)昌阿,我們稱之為non-flag參數(shù)

parseOne方法中接下來是處理-flag=x,然后是-flag(bool類型)(這里對bool進(jìn)行了特殊處理)恳邀,接著是-flag x這種形式懦冰,最后,將解析成功的Flag實例存入FlagSet的actual map中谣沸。

Arg(i int)和Args()儿奶、NArg()、NFlag()
Arg(i int)和Args()這兩個方法就是獲取non-flag參數(shù)的鳄抒;NArg()獲得non-flag個數(shù);NFlag()獲得FlagSet中actual長度(即被設(shè)置了的參數(shù)個數(shù))椰弊。

flag解析遇到non-flag參數(shù)就停止了许溅。所以如果我們將non-flag參數(shù)放在最前面,flag什么也不會解析秉版,因為flag遇到了這個就停止解析了贤重。

三:分支程序

根據(jù)參數(shù)值,代碼進(jìn)入分支程序清焕,執(zhí)行相關(guān)功能并蝗。上面代碼提供了 -h 參數(shù)的功能執(zhí)行。

if h || H {
        flag.Usage()
    }

總體而言秸妥,從例子上看滚停,flag package很有用,但是并沒有強(qiáng)大到解析一切的程度粥惧。如果你的入?yún)⒔馕龇浅?fù)雜键畴,flag可能捉襟見肘。

Cobra是一個用來創(chuàng)建強(qiáng)大的現(xiàn)代CLI命令行的Go開源庫突雪。開源包可能比較合適構(gòu)建更為復(fù)雜的命令行程序起惕。開源地址:https://github.com/spf13/cobra

本書《Go語言四十二章經(jīng)》內(nèi)容在github上同步地址:https://github.com/ffhelicopter/Go42
本書《Go語言四十二章經(jīng)》內(nèi)容在簡書同步地址: http://www.reibang.com/nb/29056963

雖然本書中例子都經(jīng)過實際運(yùn)行,但難免出現(xiàn)錯誤和不足之處咏删,煩請您指出惹想;如有建議也歡迎交流。
聯(lián)系郵箱:roteman@163.com

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末督函,一起剝皮案震驚了整個濱河市嘀粱,隨后出現(xiàn)的幾起案子激挪,更是在濱河造成了極大的恐慌,老刑警劉巖草穆,帶你破解...
    沈念sama閱讀 212,383評論 6 493
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件灌灾,死亡現(xiàn)場離奇詭異,居然都是意外死亡悲柱,警方通過查閱死者的電腦和手機(jī)锋喜,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,522評論 3 385
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來豌鸡,“玉大人嘿般,你說我怎么就攤上這事⊙墓冢” “怎么了炉奴?”我有些...
    開封第一講書人閱讀 157,852評論 0 348
  • 文/不壞的土叔 我叫張陵,是天一觀的道長蛇更。 經(jīng)常有香客問我瞻赶,道長,這世上最難降的妖魔是什么派任? 我笑而不...
    開封第一講書人閱讀 56,621評論 1 284
  • 正文 為了忘掉前任砸逊,我火速辦了婚禮,結(jié)果婚禮上掌逛,老公的妹妹穿的比我還像新娘师逸。我一直安慰自己,他們只是感情好豆混,可當(dāng)我...
    茶點故事閱讀 65,741評論 6 386
  • 文/花漫 我一把揭開白布篓像。 她就那樣靜靜地躺著,像睡著了一般皿伺。 火紅的嫁衣襯著肌膚如雪员辩。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,929評論 1 290
  • 那天鸵鸥,我揣著相機(jī)與錄音屈暗,去河邊找鬼。 笑死脂男,一個胖子當(dāng)著我的面吹牛养叛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播宰翅,決...
    沈念sama閱讀 39,076評論 3 410
  • 文/蒼蘭香墨 我猛地睜開眼弃甥,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了汁讼?” 一聲冷哼從身側(cè)響起淆攻,我...
    開封第一講書人閱讀 37,803評論 0 268
  • 序言:老撾萬榮一對情侶失蹤阔墩,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后瓶珊,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體啸箫,經(jīng)...
    沈念sama閱讀 44,265評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,582評論 2 327
  • 正文 我和宋清朗相戀三年伞芹,在試婚紗的時候發(fā)現(xiàn)自己被綠了忘苛。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 38,716評論 1 341
  • 序言:一個原本活蹦亂跳的男人離奇死亡唱较,死狀恐怖扎唾,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情南缓,我是刑警寧澤胸遇,帶...
    沈念sama閱讀 34,395評論 4 333
  • 正文 年R本政府宣布,位于F島的核電站汉形,受9級特大地震影響纸镊,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜概疆,卻給世界環(huán)境...
    茶點故事閱讀 40,039評論 3 316
  • 文/蒙蒙 一逗威、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧届案,春花似錦、人聲如沸罢艾。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,798評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽咐蚯。三九已至童漩,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間春锋,已是汗流浹背矫膨。 一陣腳步聲響...
    開封第一講書人閱讀 32,027評論 1 266
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點兒被人妖公主榨干…… 1. 我叫王不留期奔,地道東北人侧馅。 一個月前我還...
    沈念sama閱讀 46,488評論 2 361
  • 正文 我出身青樓,卻偏偏與公主長得像呐萌,于是被迫代替她去往敵國和親馁痴。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 43,612評論 2 350

推薦閱讀更多精彩內(nèi)容

  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理肺孤,服務(wù)發(fā)現(xiàn)罗晕,斷路器济欢,智...
    卡卡羅2017閱讀 134,637評論 18 139
  • #口語粉碎機(jī)# L1 Day20【打卡序列04】 過去分詞 1. vanished youth 翻譯:逝去的青春 ...
    安墨一生Ivy閱讀 693評論 0 0
  • 星星咬了我一口 太溫柔的眸 只一眼 那細(xì)碎的疼痛 用來紀(jì)念吧 見過的精靈都說 于是,癢...
    未曉啊閱讀 118評論 0 0
  • 寶貝睡著了才有時間畫的小渊,昨天畫了個大概法褥,今天竣工,還是不夠細(xì)膩酬屉,紋路還是亂了一些
    蜀南枚閱讀 208評論 2 2
  • 窗外梆惯,或雨聲嘀嗒酱鸭,或月光皎潔。窗內(nèi)垛吗,一片靜謐凹髓。不大的空間里彌漫著檀香淡淡的香味,眼前是色彩與靈感的的碰撞怯屉,內(nèi)心里交...
    徽韻蒹葭閱讀 2,674評論 50 63