最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

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

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

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

特點

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

  • 實現(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 中 --- 具有不同含義,這點稍后會進行介紹。

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

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

進階用法

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

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)志進行重排序。

示例最后,使用 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ù)運行示例:

$ 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,并且可能為負數(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)志名進行了規(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ù)運行示例:

$ 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ù)運行示例:

$ 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)志集合了。

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

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

總結(jié)

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

首先介紹了 pflag 的基本使用方法,包括聲明標(biāo)志、解析命令行參數(shù)、獲取標(biāo)志值等。接著介紹了 pflag 的進階用法,例如自定義 FlagSet、使用 pflag.<Type>P 方法來支持簡短標(biāo)志。之后又對命令行標(biāo)志語法進行了講解,對于布爾值、非布爾值和簡短標(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)志源自官方示例,不過我順勢而為又聲明了 porthost 標(biāo)志,算是一個程序中的諧音梗 :)。

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

相關(guān)文章

  • Golang中int類型和字符串類型相互轉(zhuǎn)換的實現(xiàn)方法

    Golang中int類型和字符串類型相互轉(zhuǎn)換的實現(xiàn)方法

    在日常開發(fā)中,經(jīng)常需要將數(shù)字轉(zhuǎn)換為字符串或者將字符串轉(zhuǎn)換為數(shù)字,在 Golang 中,有一些很簡便的方法可以實現(xiàn)這個功能,接下來就詳細講解一下如何實現(xiàn) int 類型和字符串類型之間的互相轉(zhuǎn)換,需要的朋友可以參考下
    2023-09-09
  • Go語言的管道Channel用法實例

    Go語言的管道Channel用法實例

    這篇文章主要介紹了Go語言的管道Channel用法,實例分析了Go語言中管道的原理與使用技巧,具有一定參考借鑒價值,需要的朋友可以參考下
    2015-02-02
  • 一文詳解Golang內(nèi)存管理之??臻g管理

    一文詳解Golang內(nèi)存管理之??臻g管理

    這篇文章主要介紹了Golang內(nèi)存管理的棧空間管理,文章通過代碼示例介紹的非常詳細,對我們學(xué)習(xí)Golang內(nèi)存管理有一定的幫助,需要的朋友跟著小編一起來學(xué)習(xí)吧
    2023-06-06
  • golang拼接字符串的5種實現(xiàn)方式

    golang拼接字符串的5種實現(xiàn)方式

    文章總結(jié)了五種拼接字符串的方式,包括使用 "+"、strings.Join()、fmt.Sprint、bytes.Buffer 和 strings.Builder,每種方式都有其適用場景和性能特點
    2024-12-12
  • Go語言通道之無緩沖通道與緩沖通道詳解

    Go語言通道之無緩沖通道與緩沖通道詳解

    通道是一種特殊的數(shù)據(jù)結(jié)構(gòu),可以在協(xié)程之間進行傳遞數(shù)據(jù),從而實現(xiàn)協(xié)程之間的通信和同步,本文就來和大家講講Go語言通道中的無緩沖通道與緩沖通道吧
    2023-06-06
  • Go語言實戰(zhàn)之切片內(nèi)存優(yōu)化

    Go語言實戰(zhàn)之切片內(nèi)存優(yōu)化

    Go 語言的切片是一個動態(tài)的數(shù)據(jù)結(jié)構(gòu),可以方便地對其進行擴容和縮容操作。這篇文章主要為大家詳細介紹了Go語言如何實現(xiàn)切片內(nèi)存優(yōu)化,需要的可以參考一下
    2023-03-03
  • Go語言通過http抓取網(wǎng)頁的方法

    Go語言通過http抓取網(wǎng)頁的方法

    這篇文章主要介紹了Go語言通過http抓取網(wǎng)頁的方法,實例分析了Go語言通過http操作頁面的技巧,需要的朋友可以參考下
    2015-03-03
  • golang 函數(shù)返回chan類型的操作

    golang 函數(shù)返回chan類型的操作

    這篇文章主要介紹了golang 函數(shù)返回chan類型的操作,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2021-04-04
  • 使用pprof分析golang內(nèi)存泄露問題及解決

    使用pprof分析golang內(nèi)存泄露問題及解決

    這篇文章主要介紹了使用pprof分析golang內(nèi)存泄露問題及解決,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
    2025-04-04
  • Golang分布式鎖詳細介紹

    Golang分布式鎖詳細介紹

    分布式鎖是控制分布式系統(tǒng)之間同步訪問共享資源的一種方式。如果不同的系統(tǒng)或是同一個系統(tǒng)的不同主機之間共享了一個或一組資源,那么訪問這些資源時,需要通過一些互斥手段來防止彼此之間的干擾以保證一致性,在這種情況下,就需要使用分布式鎖了
    2022-10-10

最新評論

兰州市| 黎城县| 青阳县| 德安县| 西青区| 迁西县| 和顺县| 孝义市| 阜康市| 璧山县| 四川省| 溧水县| 社旗县| 文山县| 江门市| 永福县| 铜鼓县| 杂多县| 阳朔县| 应用必备| 南陵县| 邛崃市| 闸北区| 叙永县| 阿拉善左旗| 湄潭县| 涡阳县| 汨罗市| 若尔盖县| 高平市| 通化县| 潜山县| 湘阴县| 日喀则市| 广灵县| 蓬溪县| 香格里拉县| 藁城市| 曲周县| 乌鲁木齐县| 陕西省|