1. 程式人生 > 實用技巧 >Golang的spf13/pflag入門示例

Golang的spf13/pflag入門示例

pflag 包的主要特點

  • 支援更加精細的引數型別: uintuint64uint8uint16int32等型別。
  • 支援更多引數型別:ipip maskip netcount、以及所有型別的 slice 型別。
  • 相容標準 flag 庫的 Flag 和 FlagSet:pflag 更像是對 flag 的擴充套件。
  • 原生支援更豐富的功能:支援 shorthanddeprecatedhidden 等高階功能。

安裝 pflag 包

新增pflag包,用下面的命令安裝該包:

go get github.com/spf13/pflag

入門 demo

Go workspace

sr 目錄下建立 pflagdemo 目錄,並在目錄下建立 main.go 檔案,編輯其內容如下:

package main

import flag "github.com/spf13/pflag"
import (
    "fmt"
    "strings"
)

// 定義命令列引數對應的變數
var cliName = flag.StringP("name", "n", "nick", "Input Your Name")
var cliAge = flag.IntP("age", "a",22, "Input Your Age")
var cliGender = flag.StringP("gender", "g","male", "Input Your Gender")
var cliOK = flag.BoolP("ok", "o", false, "Input Are You OK")
var cliDes = flag.StringP("des-detail", "d", "", "Input Description")
var cliOldFlag = flag.StringP("badflag", "b", "just for test", "Input badflag")

func wordSepNormalizeFunc(f *flag.FlagSet, name string) flag.NormalizedName {
    from := []string{"-", "_"}
    to := "."
    for _, sep := range from {
        name = strings.Replace(name, sep, to, -1)
    }
    return flag.NormalizedName(name)
}

func main() {
    // 設定標準化引數名稱的函式
    flag.CommandLine.SetNormalizeFunc(wordSepNormalizeFunc)

    // 為 age 引數設定 NoOptDefVal
    flag.Lookup("age").NoOptDefVal = "25"

    // 把 badflag 引數標記為即將廢棄的,請使用者使用 des-detail 引數
    flag.CommandLine.MarkDeprecated("badflag", "please use --des-detail instead")

    // 把 badflag 引數的 shorthand 標記為即將廢棄的,請使用者使用 des-detail 的 shorthand 引數
    flag.CommandLine.MarkShorthandDeprecated("badflag", "please use -d instead")

    // 在幫助文件中隱藏引數 gender
    flag.CommandLine.MarkHidden("badflag")

    // 把使用者傳遞的命令列引數解析為對應變數的值
    flag.Parse()

    fmt.Println("name=", *cliName)
    fmt.Println("age=", *cliAge)
    fmt.Println("gender=", *cliGender)
    fmt.Println("ok=", *cliOK)
    fmt.Println("des=", *cliDes)
}

執行 demo

在 flagdemo 目錄下執行 go build 命令編譯 demo 生成可執行檔案 flagdemo。下面我們通過執行 demo 程式來了解 pflag 包命令列引數的語法特點。

布林型別的引數
布林型別的引數有下面幾種寫法

--flag               // 等同於 --flag=true        
--flag=value
--flag value         // 這種寫法只有在沒有設定預設值時才生效

NoOptDefVal 用法

pflag 包支援通過簡便的方式為引數設定預設值之外的值,實現方式為設定引數的 NoOptDefVal 屬性:

var cliAge = flag.IntP("age", "a",22, "Input Your Age")
flag.Lookup("age").NoOptDefVal = "25"

下面是傳遞引數的方式和引數最終的取值:

Parsed Arguments     Resulting Value
--age=30             cliAge=30
--age                cliAge=25
[nothing]            cliAge=22

shorthand

與 flag 包不同,在 pflag 包中,選項名稱前面的 --- 是不一樣的。- 表示 shorthand-- 表示完整的選項名稱。

除了最後一個 shorthand,其它的 shorthand 都必須是布林型別的引數或者是具有預設值的引數。
所以對於布林型別的引數和設定了 NoOptDefVal 的引數可以寫成下面的形式:

-o
-o=true
// 注意,下面的寫法是不正確的
-o true

非布林型別的引數和沒有設定 NoOptDefVal 的引數的寫法如下:

-g female
-g=female
-gfemale

日常的使用中一般會混合上面的兩類規則:

-aon "jack"
-aon="jack"
-aon"jack"
-aonjack
-oa=35

注意 -- 後面的引數不會被解析:

-oa=35 -- -gfemale

標準化引數的名稱

如果我們建立了名稱為 --des-detail 的引數,但是使用者卻在傳參時寫成了 --des_detail--des.detail 會怎麼樣?預設情況下程式會報錯退出,但是我們可以通過 pflag 提供的 SetNormalizeFunc 功能輕鬆的解決這個問題:

func wordSepNormalizeFunc(f *flag.FlagSet, name string) flag.NormalizedName {
    from := []string{"-", "_"}
    to := "."
    for _, sep := range from {
        name = strings.Replace(name, sep, to, -1)
    }
    return flag.NormalizedName(name)
}
flag.CommandLine.SetNormalizeFunc(wordSepNormalizeFunc)

這樣,下面的寫法也能識別了:

--des_detail="person detail"

把引數標記為即將廢棄

在程式的不斷升級中新增新的引數和廢棄舊的引數都是常見的用例,pflag 包對廢棄引數也提供了很好的支援。通過 MarkDeprecated 和 MarkShorthandDeprecated 方法可以分別把引數及其 shorthand 標記為廢棄:

// 把 badflag 引數標記為即將廢棄的,請使用者使用 des-detail 引數
flag.CommandLine.MarkDeprecated("badflag", "please use --des-detail instead")

// 把 badflag 引數的 shorthand 標記為即將廢棄的,請使用者使用 des-detail 的 shorthand 引數
flag.CommandLine.MarkShorthandDeprecated("badflag", "please use -d instead")

在幫助文件中隱藏引數

pflag 包還支援在引數說明中隱藏引數的功能:

// 在幫助文件中隱藏引數 badflag
flag.CommandLine.MarkHidden("badflag")

這樣,幫助文件中則不會顯示 badflag 的資訊。其實在把引數標記為廢棄時,同時也會設定隱藏引數。



點選這裡

作者:半獸人
連結:https://www.orchome.com/9669
來源:OrcHome
著作權歸作者所有。商業轉載請聯絡作者獲得授權,非商業轉載請註明出處。