概述
flag包提供了一系列解析命令行參數的功能接口
命令行語法
命令行語法主要有以下幾種形式
-flag //只支持bool類型 -flag=x -flag x //只支持非bool類型
以上語法對於一個或兩個‘-’號,效果是一樣的,但是要注意對於第三種情況,只支持非bool類型,原因是碰到如下情況時
cmd -x *
*為0,false有可能表示一個文件名或文件,也有可能表示x標簽的值為0或false,會產生二義性,因此規定第三種只支持非bool類型。對於整形flag,合法的值可以為1234, 0664,0x1234或負數等。對於布爾型flag,可以為1, 0, t, f, T, F,true, false, TRUE, FALSE, True, False等
命令行參數解析方法
使用flag主要包括以下幾步
-
定義flag參數,有三種方式
-
通過
flag.String(), Bool(), Int()等flag.Xxx()方法,該種方式返回一個相應的指針import "flag" var ip = flag.Int("flagname", 1234, "help message for flagname") -
通過
flag.XxxVar()方法將flag綁定到一個變量,該種方式返回值類型,如var flagvar int func init() { flag.IntVar(&flagvar, "flagname", 1234, "help message for flagname") } -
通過
flag.Var()綁定自定義類型,自定義類型需要實現Value接口(Receives必須為指針),如flag.Var(&flagVal, "name", "help message for flagname")對於這種類型的flag,默認值為該變量類型的初始值
-
-
調用
flag.Parse()解析命令行參數到定義的flagflag.Parse()解析函數將會在碰到第一個非flag命令行參數時停止,非flag命令行參數是指不滿足命令行語法的參數,如命令行參數為
cmd --flag=true abc則第一個非flag命令行參數為“abc” -
調用Parse解析后,就可以直接使用flag本身(指針類型)或者綁定的變量了(值類型)
fmt.Println("ip has value ", *ip) fmt.Println("flagvar has value ", flagvar)還可通過
flag.Args(),flag.Arg(i)來獲取非flag命令行參數 -
如果需要每個函數的詳細demo,可參見Gopkg:flag
示例
-
示例1: 獲取“species” flag的值,默認為“gopher”
var species = flag.String("species", "gopher", "the species we are studying") -
示例2: 兩個flag共享同一個變量,一般用於同時實現完整flag參數和對應簡化版flag參數,需要注意初始化順序和默認值
var gopherType string func init() { const ( defaultGopher = "pocket" usage = "the variety of gopher" ) flag.StringVar(&gopherType, "gopher_type", defaultGopher, usage) flag.StringVar(&gopherType, "g", defaultGopher, usage+"(shorthand)") } -
示例3: 將flag綁定用戶自定義類型。按我們先前所說,只需要實現Value接口,但實際上,如果需要取值的話,需要實現Getter接口,看下接口定義就明白了:
type Getter interface { Value Get(string) interface{} } type Value interface { String() string Set(string) error }接下來,我們實現一個解析並格式化命令行輸入的時間集合的例子,如下
package main import ( "errors" "flag" "fmt" "strings" "time" ) type interval []time.Duration //實現String接口 func (i *interval) String() string { return fmt.Sprintf("%v", *i) } //實現Set接口,Set接口決定了如何解析flag的值 func (i *interval) Set(value string) error { //此處決定命令行是否可以設置多次-deltaT if len(*i) > 0 { return errors.New("interval flag already set") } for _, dt := range strings.Split(value, ",") { duration, err := time.ParseDuration(dt) if err != nil { return err } *i = append(*i, duration) } return nil } var intervalFlag interval func init() { flag.Var(&intervalFlag, "deltaT", "comma-separated list of intervals to use between events") } func main() { flag.Parse() fmt.Println(intervalFlag) }運行結果:
//./commandLine -deltaT 61m,72h,80s [1h1m0s 72h0m0s 1m20s]
