亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

Go語言中命令行參數(shù)解析工具pflag的使用指南

 更新時間:2024年11月04日 09:37:56   作者:江湖十年  
在使用?Go?進(jìn)行開發(fā)的過程中,命令行參數(shù)解析是我們經(jīng)常遇到的需求,于是?Go?社區(qū)中出現(xiàn)了一個叫?pflag?的第三方包,功能更加全面且足夠強(qiáng)大,下面我們就來看看它的具體使用吧

在使用 Go 進(jìn)行開發(fā)的過程中,命令行參數(shù)解析是我們經(jīng)常遇到的需求。盡管 Go 標(biāo)準(zhǔn)庫提供了 flag 包用于實現(xiàn)命令行參數(shù)解析,但只能滿足基本需要,不支持高級特性。于是 Go 社區(qū)中出現(xiàn)了一個叫 pflag 的第三方包,功能更加全面且足夠強(qiáng)大。在本文中,我們將學(xué)習(xí)并掌握如何使用 pflag。

特點(diǎn)

pflag 作為 Go 內(nèi)置 flag 包的替代品,具有如下特點(diǎn):

  • 實現(xiàn)了 POSIX/GNU 風(fēng)格的 --flags。
  • pflag 與《The GNU C Library》 中「25.1.1 程序參數(shù)語法約定」章節(jié)中 POSIX 建議語法兼容。
  • 兼容 Go 標(biāo)準(zhǔn)庫中的 flag 包。如果直接使用 flag 包定義的全局 FlagSet 對象 CommandLine,則完全兼容;否則當(dāng)你手動實例化了 FlagSet 對象,這時就需要為每個標(biāo)志設(shè)置一個簡短標(biāo)志(Shorthand)。

使用

基本用法

我們可以像使用 Go 標(biāo)準(zhǔn)庫中的 flag 包一樣使用 pflag。

package main

import (
 "fmt"

 "github.com/spf13/pflag"
)

type host struct {
 value string
}

func (h *host) String() string {
 return h.value
}

func (h *host) Set(v string) error {
 h.value = v
 return nil
}

func (h *host) Type() string {
 return "host"
}

func main() {
 var ip *int = pflag.Int("ip", 1234, "help message for ip")

 var port int
 pflag.IntVar(&port, "port", 8080, "help message for port")

 var h host
 pflag.Var(&h, "host", "help message for host")

 // 解析命令行參數(shù)
 pflag.Parse()

 fmt.Printf("ip: %d\n", *ip)
 fmt.Printf("port: %d\n", port)
 fmt.Printf("host: %+v\n", h)

 fmt.Printf("NFlag: %v\n", pflag.NFlag()) // 返回已設(shè)置的命令行標(biāo)志個數(shù)
 fmt.Printf("NArg: %v\n", pflag.NArg())   // 返回處理完標(biāo)志后剩余的參數(shù)個數(shù)
 fmt.Printf("Args: %v\n", pflag.Args())   // 返回處理完標(biāo)志后剩余的參數(shù)列表
 fmt.Printf("Arg(1): %v\n", pflag.Arg(1)) // 返回處理完標(biāo)志后剩余的參數(shù)列表中第 i 項
}

以上示例演示的 pflag 用法跟 flag 包用法一致,可以做到二者無縫替換。

示例分別使用 pflag.Int()pflag.IntVar()、pflag.Var() 三種不同方式來聲明標(biāo)志。其中 ipport 都是 int 類型標(biāo)志,host 標(biāo)志則為自定義的 host 類型,它實現(xiàn)了 pflag.Value 接口,通過實現(xiàn)接口類型,標(biāo)志能夠支持任意類型,增加靈活性。

通過 --help/-h 參數(shù)查看命令行程序使用幫助:

$ go run main.go --help                      
Usage of ./main:
      --host host   help message for host
      --ip int      help message for ip (default 1234)
      --port int    help message for port (default 8080)
pflag: help requested

可以發(fā)現(xiàn),幫助信息中的標(biāo)志位置是經(jīng)過重新排序的,并不是標(biāo)志定義的順序。

與 flag 包不同的是,pflag 包參數(shù)定界符是兩個 -,而不是一個 -,在 pflag 中 --- 具有不同含義,這點(diǎn)稍后會進(jìn)行介紹。

ip 標(biāo)志的默認(rèn)參數(shù)為 1234,port 標(biāo)志的默認(rèn)參數(shù)為 8080

注意:在有些終端下執(zhí)行程序退出后,還會多打印一行 exit status 2,這并不意味著程序沒有正常退出,而是因為 --help 意圖就是用來查看使用幫助,所以程序在打印使用幫助信息后,主動調(diào)用 os.Exit(2) 退出了。

通過如下方式使用命令行程序:

$ go run main.go --ip 1 x y --host localhost a b 
ip: 1
port: 8080
host: {value:localhost}
NFlag: 2
NArg: 4
Args: [x y a b]
Arg(1): y

ip 標(biāo)志的默認(rèn)值已被命令行參數(shù) 1 所覆蓋,由于沒有傳遞 port 標(biāo)志,所以打印結(jié)果為默認(rèn)值 8080host 標(biāo)志的值也能夠被正常打印。

還有 4 個非選項參數(shù)數(shù) x、y、ab 也都被 pflag 識別并記錄了下來。這點(diǎn)比 flag 要強(qiáng)大,在 flag 包中,非選項參數(shù)數(shù)只能寫在所有命令行參數(shù)最后,x、y 出現(xiàn)在這里程序是會報錯的。

進(jìn)階用法

除了像 flag 包一樣的用法,pflag 還支持一些獨(dú)有的用法,以下是用法示例。

package main

import (
 "fmt"
 "os"

 "github.com/spf13/pflag"
)

type host struct {
 value string
}

func (h *host) String() string {
 return h.value
}

func (h *host) Set(v string) error {
 h.value = v
 return nil
}

func (h *host) Type() string {
 return "host"
}

func main() {
 flagset := pflag.NewFlagSet("test", pflag.ExitOnError)

 var ip = flagset.IntP("ip", "i", 1234, "help message for ip")

 var boolVar bool
 flagset.BoolVarP(&boolVar, "boolVar", "b", true, "help message for boolVar")

 var h host
 flagset.VarP(&h, "host", "H", "help message for host")

 flagset.SortFlags = false

 flagset.Parse(os.Args[1:])

 fmt.Printf("ip: %d\n", *ip)
 fmt.Printf("boolVar: %t\n", boolVar)
 fmt.Printf("host: %+v\n", h)

 i, err := flagset.GetInt("ip")
 fmt.Printf("i: %d, err: %v\n", i, err)
}

首先我們通過 pflag.NewFlagSet 自定義了 FlagSet 對象 flagset,之后的標(biāo)志定義和解析都通過 flagset 來完成。

前文示例中 pflag.Int() 這種用法,實際上使用的是全局 FlagSet 對象 CommandLine,CommandLine 定義如下:

var CommandLine = NewFlagSet(os.Args[0], ExitOnError)

現(xiàn)在同樣使用三種不同方式來聲明標(biāo)志,分別為 flagset.IntP()、flagset.BoolVarP()、flagset.VarP()。不難發(fā)現(xiàn),這三個方法的命名結(jié)尾都多了一個 P,它們的能力也得以升級,三個方法都多了一個 shorthand string 參數(shù)(flagset.IntP 的第 2 個參數(shù),flagset.BoolVarPflagset.VarP 的第 3 個參數(shù))用來設(shè)置簡短標(biāo)志。

從聲明標(biāo)志的方法名中我們能夠總結(jié)出一些規(guī)律:

  • pflag.<Type> 類方法名會將標(biāo)志參數(shù)值存儲在指針中并返回。
  • pflag.<Type>Var 類方法名中包含 Var 關(guān)鍵字的,會將標(biāo)志參數(shù)值綁定到第一個指針類型的參數(shù)。
  • pflag.<Type>P、pflag.<Type>VarP 類方法名以 P 結(jié)尾的,支持簡短標(biāo)志。

一個完整標(biāo)志在命令行傳參時使用的分界符為 --,而一個簡短標(biāo)志的分界符則為 -。

flagset.SortFlags = false 作用是禁止打印幫助信息時對標(biāo)志進(jìn)行重排序。

示例最后,使用 flagset.GetInt() 獲取參數(shù)的值。

通過 --help/-h 參數(shù)查看命令行程序使用幫助:

$ go run main.go --help
Usage of test:
  -i, --ip int      help message for ip (default 1234)
  -b, --boolVar     help message for boolVar (default true)
  -H, --host host   help message for host
pflag: help requested

這次的幫助信息中,標(biāo)志順序沒有被改變,就是聲明的順序。

每一個標(biāo)志都會對應(yīng)一個簡短標(biāo)志,如 -b--boolVar 是等價的,可以更加方便的設(shè)置參數(shù)。

指定如下命令行參數(shù)運(yùn)行示例:

$ go run main.go --ip 1 -H localhost --boolVar=false
ip: 1
boolVar: false
host: {value:localhost}
i: 1, err: <nil>

通過 --ip 1 使用完整標(biāo)志指定 ip 參數(shù)值。

通過 -H localhost 使用簡短標(biāo)志指定 host 參數(shù)值。

布爾類型的標(biāo)志指定參數(shù) --boolVar=false 需要使用等號 = 而非空格。

命令行標(biāo)志語法

命令行標(biāo)志遵循如下語法:

語法說明
--flag適用于 bool 類型標(biāo)志,或具有 NoOptDefVal 屬性的標(biāo)志。
--flag x適用于非 bool 類型標(biāo)志,或沒有 NoOptDefVal 屬性的標(biāo)志。
--flag=x適用于 bool 類型標(biāo)志。
-n 1234/-n=1234/-n1234簡短標(biāo)志,非 bool 類型且沒有 NoOptDefVal 屬性,三者等價。

標(biāo)志解析在終止符 -- 之后停止。

整數(shù)標(biāo)志接受 1234、0664、0x1234,并且可能為負(fù)數(shù)。

布爾標(biāo)志接受 1, 0, t, f, true, false, TRUE, FALSE, True, False。

Duration 標(biāo)志接受任何對 time.ParseDuration 有效的輸入。

標(biāo)志名 Normalize

借助 pflag.NormalizedName 我們能夠給標(biāo)志起一個或多個別名、規(guī)范化標(biāo)志名等。

package main

import (
 "fmt"
 "os"
 "strings"

 "github.com/spf13/pflag"
)

func normalizeFunc(f *pflag.FlagSet, name string) pflag.NormalizedName {
 // alias
 switch name {
 case "old-flag-name":
  name = "new-flag-name"
  break
 }

 // --my-flag == --my_flag == --my.flag
 from := []string{"-", "_"}
 to := "."
 for _, sep := range from {
  name = strings.Replace(name, sep, to, -1)
 }
 return pflag.NormalizedName(name)
}

func main() {
 flagset := pflag.NewFlagSet("test", pflag.ExitOnError)

 var ip = flagset.IntP("new-flag-name", "i", 1234, "help message for new-flag-name")
 var myFlag = flagset.IntP("my-flag", "m", 1234, "help message for my-flag")

 flagset.SetNormalizeFunc(normalizeFunc)
 flagset.Parse(os.Args[1:])

 fmt.Printf("ip: %d\n", *ip)
 fmt.Printf("myFlag: %d\n", *myFlag)
}

要使用 pflag.NormalizedName,我們需要創(chuàng)建一個函數(shù) normalizeFunc,然后將其通過 flagset.SetNormalizeFunc(normalizeFunc) 注入到 flagset 使其生效。

normalizeFunc 函數(shù)中,我們給 new-flag-name 標(biāo)志起了一個別名 old-flag-name。

另外,還對標(biāo)志名進(jìn)行了規(guī)范化處理,帶有 -_ 分割符的標(biāo)志名,會統(tǒng)一規(guī)范化成以 . 作為分隔符的標(biāo)志名。

使用示例如下:

$ go run pflag.go --old-flag-name 2 --my-flag 200
ip: 2
myFlag: 200

$ go run pflag.go --new-flag-name 3 --my_flag 300
ip: 3
myFlag: 300

NoOptDefVal

NoOptDefValno option default values 的簡寫。

創(chuàng)建標(biāo)志后,可以為標(biāo)志設(shè)置 NoOptDefVal 屬性,如果標(biāo)志具有 NoOptDefVal 屬性并且在命令行上設(shè)置了標(biāo)志而沒有參數(shù)選項,則標(biāo)志將設(shè)置為 NoOptDefVal 指定的值。

如下示例:

var ip = flag.IntP("flagname", "f", 1234, "help message")
flag.Lookup("flagname").NoOptDefVal = "4321"

不同參數(shù)結(jié)果如下:

命令行參數(shù)結(jié)果值
--flagname=1357ip=1357
--flagnameip=4321
[nothing]ip=1234

棄用/隱藏標(biāo)志

使用 flags.MarkDeprecated 可以棄用一個標(biāo)志,使用 flags.MarkShorthandDeprecated 可以棄用一個簡短標(biāo)志,使用 flags.MarkHidden 可以隱藏一個標(biāo)志。

package main

import (
 "fmt"
 "os"

 "github.com/spf13/pflag"
)

func main() {
 flags := pflag.NewFlagSet("test", pflag.ExitOnError)

 var ip = flags.IntP("ip", "i", 1234, "help message for ip")

 var boolVar bool
 flags.BoolVarP(&boolVar, "boolVar", "b", true, "help message for boolVar")

 var h string
 flags.StringVarP(&h, "host", "H", "127.0.0.1", "help message for host")

 // 棄用標(biāo)志
 flags.MarkDeprecated("ip", "deprecated")
 flags.MarkShorthandDeprecated("boolVar", "please use --boolVar only")

 // 隱藏標(biāo)志
 flags.MarkHidden("host")

 flags.Parse(os.Args[1:])

 fmt.Printf("ip: %d\n", *ip)
 fmt.Printf("boolVar: %t\n", boolVar)
 fmt.Printf("host: %+v\n", h)
}

查看使用幫助:

$ go run main.go -h                                 
Usage of test:
      --boolVar   help message for boolVar (default true)
pflag: help requested

從打印結(jié)果可以發(fā)現(xiàn),棄用標(biāo)志 ip 時,其對應(yīng)的簡短標(biāo)志 i 也會跟著被棄用;棄用 boolVar 所對應(yīng)的簡短標(biāo)志 b 時,boolVar 標(biāo)志會被保留;host 標(biāo)志則完全被隱藏。

指定如下命令行參數(shù)運(yùn)行示例:

$ go run main.go --ip 1 --boolVar=false -H localhost
Flag --ip has been deprecated, deprecated
ip: 1
boolVar: false
host: localhost

打印信息中會提示用戶 ip 標(biāo)志已經(jīng)棄用,不過使用 --ip 1 指定的參數(shù)值依然能夠生效。

隱藏的 host 標(biāo)志使用 -H localhost 指定參數(shù)值同樣能夠生效。

指定如下命令行參數(shù)運(yùn)行示例:

$ go run main.go -i 1 -b=false --host localhost
Flag --ip has been deprecated, deprecated
Flag shorthand -b has been deprecated, please use --boolVar only
ip: 1
boolVar: false
host: localhost

打印信息中增加了一條簡短標(biāo)志 -b 已被棄用的提示,指定參數(shù)值依然生效。

對于棄用的 ip 標(biāo)志,使用簡短標(biāo)志形式傳慘 -i 1 同樣生效。

支持 flag 類型

由于 pflag 對 flag 包兼容,所以可以在一個程序中混用二者:

package main

import (
 "flag"
 "fmt"

 "github.com/spf13/pflag"
)

func main() {
 var ip *int = pflag.Int("ip", 1234, "help message for ip")
 var port *int = flag.Int("port", 80, "help message for port")

 pflag.CommandLine.AddGoFlagSet(flag.CommandLine)
 pflag.Parse()

 fmt.Printf("ip: %d\n", *ip)
 fmt.Printf("port: %d\n", *port)
}

其中,ip 標(biāo)志是使用 pflag.Int() 聲明的,port 標(biāo)志則是使用 flag.Int() 聲明的。只需要通過 AddGoFlagSet 方法將 flag.CommandLine 注冊到 pflag 中,那么 pflag 就可以使用 flag 中聲明的標(biāo)志集合了。

運(yùn)行示例結(jié)果如下:

$ go run main.go --ip 10 --port 8000
ip: 10
port: 8000

總結(jié)

本文主要介紹了 Go第三方標(biāo)志包 pflag 的特點(diǎn)及用法。

首先介紹了 pflag 的基本使用方法,包括聲明標(biāo)志、解析命令行參數(shù)、獲取標(biāo)志值等。接著介紹了 pflag 的進(jìn)階用法,例如自定義 FlagSet、使用 pflag.<Type>P 方法來支持簡短標(biāo)志。之后又對命令行標(biāo)志語法進(jìn)行了講解,對于布爾值、非布爾值和簡短標(biāo)志,都有各自不同的語法。我們還講解了如何借助 pflag.NormalizedName 給標(biāo)志起一個或多個別名、規(guī)范化標(biāo)志名。然后介紹了 NoOptDefVal 的作用和如何棄用/隱藏標(biāo)志。最后通過示例演示了如何在一個程序中混用 flag 和 pflag。

彩蛋:不知道你有沒有發(fā)現(xiàn),示例中的 ip 標(biāo)志的名稱其實代表的是 int pointer 而非 Internet Protocol Addressip 標(biāo)志源自官方示例,不過我順勢而為又聲明了 port、host 標(biāo)志,算是一個程序中的諧音梗 :)。

以上就是Go語言中命令行參數(shù)解析工具pflag的使用指南的詳細(xì)內(nèi)容,更多關(guān)于Go pflag命令行參數(shù)解析的資料請關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • 詳解Go函數(shù)和方法之間有什么區(qū)別

    詳解Go函數(shù)和方法之間有什么區(qū)別

    這篇文章就簡單和大家聊一聊在Go中函數(shù)與方法之間的區(qū)別,文章通過代碼示例介紹的非常詳細(xì),對我們的學(xué)習(xí)或工作有一定的幫助,感興趣的小伙伴跟著小編一起來看看吧
    2023-07-07
  • golang之JWT實現(xiàn)的示例代碼

    golang之JWT實現(xiàn)的示例代碼

    這篇文章主要介紹了golang之JWT實現(xiàn)的示例代碼,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-05-05
  • golang atomic原子操作示例詳解

    golang atomic原子操作示例詳解

    這篇文章主要為大家介紹了golang atomic原子操作示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-09-09
  • Go中使用加密算法的方法

    Go中使用加密算法的方法

    本文通過實例代碼給大家介紹go中使用加密算法的方法,代碼簡單易懂,對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友參考下吧
    2021-08-08
  • Go語言循環(huán)遍歷含有中文的字符串的方法小結(jié)

    Go語言循環(huán)遍歷含有中文的字符串的方法小結(jié)

    這篇文章主要介紹了Go語言循環(huán)遍歷含有中文的字符串的幾種方法,文章通過代碼示例講解的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴跟著小編一起來看看吧
    2023-07-07
  • Go 實現(xiàn)一次性打包各個平臺的可執(zhí)行程序

    Go 實現(xiàn)一次性打包各個平臺的可執(zhí)行程序

    這篇文章主要介紹了Go 實現(xiàn)一次性打包各個平臺的可執(zhí)行程序,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2020-12-12
  • Go語言如何處理HTTP身份驗證教程示例

    Go語言如何處理HTTP身份驗證教程示例

    這篇文章主要為大家介紹了Go語言如何處理HTTP身份驗證教程示例,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2024-01-01
  • 利用golang實現(xiàn)封裝trycatch異常處理實例代碼

    利用golang實現(xiàn)封裝trycatch異常處理實例代碼

    Go語言追求簡潔優(yōu)雅,所以go語言不支持傳統(tǒng)的 try…catch…finally 這種異常,最近發(fā)現(xiàn)了不錯的trycatch包,下面這篇文章主要跟大家分享了關(guān)于利用golang實現(xiàn)封裝trycatch異常處理的實例代碼,需要的朋友可以參考下。
    2017-07-07
  • Go語言CSP并發(fā)模型goroutine及channel底層實現(xiàn)原理

    Go語言CSP并發(fā)模型goroutine及channel底層實現(xiàn)原理

    這篇文章主要為大家介紹了Go語言CSP并發(fā)模型goroutine?channel底層實現(xiàn)原理,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-05-05
  • 淺談golang通道類型

    淺談golang通道類型

    本文主要介紹了淺談golang通道類型,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2023-02-02

最新評論