Go 学习笔记(45)— Go 标准库之 flag(命令行参数解析)
1. 參數(shù)解析說(shuō)明
import "flag"
flag 包實(shí)現(xiàn)了命令行參數(shù)的解析。每個(gè)參數(shù)認(rèn)為一條記錄,根據(jù)實(shí)際進(jìn)行定義,到一個(gè) set 集合。每條都有各自的狀態(tài)參數(shù)。
使用 flag 的正常流程為:
- 通過(guò)
flag.String(),flag.Bool(),flag.Int()等函數(shù)來(lái)定義命令行中需要使用的參數(shù); - 在定義完
flag命令行參數(shù)后,通過(guò)調(diào)用flag.Parse()來(lái)進(jìn)行對(duì)命令行參數(shù)的解析; - 獲取
flag.String(),flag.Bool(),flag.Int()等方法的返回值,即對(duì)應(yīng)用戶輸入的參數(shù);
需要注意的是:
flag.Xxx()返回的值是變量的內(nèi)存地址,要獲取值時(shí)要通過(guò)在變量前加*獲取。
flag.Int 、 flag.Bool 、 flag.String 這樣的函數(shù)格式都是一樣的,調(diào)用的時(shí)候需要傳入 3 個(gè)參數(shù)
func Int(name string, value int, usage string) *int
func Bool(name string, value bool, usage string) *bool
func String(name string, value string, usage string) *string
name 表示命令行參數(shù)的名稱, value 表示命令行參數(shù)的值, usage 表示命令行參數(shù)的說(shuō)明和描述。
其它可注冊(cè)的 flag 類型有:
Bool / Int / Int64 / Uint / Uint64 / Float / Float64 / String / Duration / Var
最簡(jiǎn)單的代碼示例:
package main// 導(dǎo)入系統(tǒng)包
import ("flag""fmt"
)// 定義命令行參數(shù)
var mode = flag.String("mode", "", "process mode")
var num = flag.Int("num", 5, "process number")
var isProcess = flag.Bool("isProcess", true, "process bool")func main() {// 解析命令行參數(shù)flag.Parse()// 輸出命令行參數(shù)fmt.Println(*mode)fmt.Println(*num)fmt.Println(*isProcess)
}
運(yùn)行結(jié)果:
wohu@wohu:~/gocode/src$ go run hello.go -h
Usage of /tmp/go-build314506183/b001/exe/hello:-isProcessprocess bool (default true)-mode stringprocess mode-num intprocess number (default 5)
exit status 2
wohu@wohu:~/gocode/src$ go run hello.go -mode="hello,world" -num=10
hello,world
10
true
wohu@wohu:~/gocode/src$
命令行 flag 語(yǔ)法:
-flag
-flag=x
-flag x // 只有非bool類型的flag可以
可以使用 1 個(gè)或 2 個(gè) - 號(hào),效果是一樣的。最后一種格式不能用于 bool 類型的 flag ,因?yàn)槿绻形募麨?0、 false 等時(shí),如下命令:
cmd -x *
其含義會(huì)改變。你必須使用 -flag=false 格式來(lái)關(guān)閉一個(gè) bool 類型 flag 。
整數(shù)flag接受1234、0664、0x1234等類型,也可以是負(fù)數(shù)。bool類型flag可以是:
1, 0, t, f, T, F, true, false, TRUE, FALSE, True, False
注意: go run hello.go -mode="hello,world" -num=10 命令行中,可以是 --num=10 但不能是 --num==10 。
2. 數(shù)據(jù)結(jié)構(gòu)和函數(shù)
2.1 type Flag
type Flag struct {Name string // flag在命令行中的名字Usage string // 幫助信息Value Value // 要設(shè)置的值DefValue string // 默認(rèn)值(文本格式),用于使用信息
}
Flag 類型代表一條 flag 的狀態(tài)。
2.2 type FlagSet
type FlagSet struct {// Usage函數(shù)在解析flag出現(xiàn)錯(cuò)誤時(shí)會(huì)被調(diào)用// 該字段為一個(gè)函數(shù)(而非采用方法),以便修改為自定義的錯(cuò)誤處理函數(shù)Usage func()// 內(nèi)含隱藏或非導(dǎo)出字段
}
FlagSet 代表一個(gè)已注冊(cè)的 flag 的集合。 FlagSet 零值沒(méi)有名字,采用 ContinueOnError 錯(cuò)誤處理策略。
在 flag 包中,進(jìn)行了進(jìn)一步封裝:將 FlagSet 的方法都重新定義了一遍,也就是提供了一序列函數(shù),而函數(shù)中只是簡(jiǎn)單的調(diào)用已經(jīng)實(shí)例化好了的 FlagSet 。
所以我們只需要關(guān)注 flag 中的函數(shù)即可,它會(huì)自動(dòng)調(diào)用 FlagSet 中的函數(shù)。
2.3 func NFlag
func NFlag() int
NFlag 返回已被設(shè)置的 flag 的數(shù)量。
2.4 func Lookup
func Lookup(name string) *Flag
返回已經(jīng)已注冊(cè) flag 的 Flag 結(jié)構(gòu)體指針;如果 flag 不存在的話,返回 nil 。
2.5 func NArg
func NArg() int
NArg 返回解析 flag 之后剩余參數(shù)的個(gè)數(shù)。
2.6 func Args
func Args() []string
返回解析之后剩下的非 flag 參數(shù)。(不包括命令名)也就是說(shuō)無(wú)法進(jìn)行flag匹配的有哪些參數(shù)。
2.7 func Arg
func Arg(i int) string
返回解析之后剩下的第 i 個(gè)參數(shù),從 0 開(kāi)始索引。
2.8 func PrintDefaults
func PrintDefaults()
PrintDefault 會(huì)向標(biāo)準(zhǔn)錯(cuò)誤輸出寫(xiě)入所有注冊(cè)好的 flag 的默認(rèn)值。
2.9 func Bool
func Bool(name string, value bool, usage string) *bool
Bool 用指定的名稱、默認(rèn)值、使用信息注冊(cè)一個(gè) bool 類型 flag 。返回一個(gè)保存了該 flag 的值的指針。
2.10 func BoolVar
func BoolVar(p *bool, name string, value bool, usage string)
BoolVar 用指定的名稱、默認(rèn)值、使用信息注冊(cè)一個(gè) bool 類型 flag ,并將 flag 的值保存到 p 指向的變量。
2.11 func Int
func Int(name string, value int, usage string) *int
Int 用指定的名稱、默認(rèn)值、使用信息注冊(cè)一個(gè) int 類型 flag 。返回一個(gè)保存了該 flag 的值的指針。
2.12 func IntVar
func IntVar(p *int, name string, value int, usage string)
IntVar 用指定的名稱、默認(rèn)值、使用信息注冊(cè)一個(gè) int 類型 flag ,并將 flag 的值保存到 p 指向的變量。
2.13 func Int64
func Int64(name string, value int64, usage string) *int64
Int64 用指定的名稱、默認(rèn)值、使用信息注冊(cè)一個(gè) int64 類型 flag 。返回一個(gè)保存了該 flag 的值的指針。
2.14 func Int64Var
func Int64Var(p *int64, name string, value int64, usage string)
Int64Var 用指定的名稱、默認(rèn)值、使用信息注冊(cè)一個(gè) int64 類型 flag ,并將 flag 的值保存到 p 指向的變量。
2.15 func Uint
func Uint(name string, value uint, usage string) *uint
Uint 用指定的名稱、默認(rèn)值、使用信息注冊(cè)一個(gè) uint 類型 flag 。返回一個(gè)保存了該 flag 的值的指針。
2.16 func UintVar
func UintVar(p *uint, name string, value uint, usage string)
UintVar 用指定的名稱、默認(rèn)值、使用信息注冊(cè)一個(gè) uint 類型 flag ,并將 flag 的值保存到 p 指向的變量。
2.17 func Uint64
func Uint64(name string, value uint64, usage string) *uint64
Uint64 用指定的名稱、默認(rèn)值、使用信息注冊(cè)一個(gè) uint64 類型 flag 。返回一個(gè)保存了該 flag 的值的指針。
2.18 func Uint64Var
func Uint64Var(p *uint64, name string, value uint64, usage string)
Uint64Var 用指定的名稱、默認(rèn)值、使用信息注冊(cè)一個(gè) uint64 類型 flag ,并將 flag 的值保存到 p 指向的變量。
2.19 func Float64
func Float64(name string, value float64, usage string) *float64
Float64 用指定的名稱、默認(rèn)值、使用信息注冊(cè)一個(gè) float64 類型 flag 。返回一個(gè)保存了該 flag 的值的指針。
2.20 func Float64Var
func Float64Var(p *float64, name string, value float64, usage string)
Float64Var 用指定的名稱、默認(rèn)值、使用信息注冊(cè)一個(gè) float64 類型 flag ,并將 flag 的值保存到 p 指向的變量。
2.21 func String
func String(name string, value string, usage string) *string
String 用指定的名稱、默認(rèn)值、使用信息注冊(cè)一個(gè) string 類型 flag 。返回一個(gè)保存了該 flag 的值的指針。
2.22 func StringVar
func StringVar(p *string, name string, value string, usage string)
StringVar 用指定的名稱、默認(rèn)值、使用信息注冊(cè)一個(gè) string 類型 flag ,并將 flag 的值保存到 p 指向的變量。
2.23 func Duration
func Duration(name string, value time.Duration, usage string) *time.Duration
Duration 用指定的名稱、默認(rèn)值、使用信息注冊(cè)一個(gè) time.Duration 類型 flag 。返回一個(gè)保存了該 flag 的值的指針。
2.24 func DurationVar
func DurationVar(p *time.Duration, name string, value time.Duration, usage string)
DurationVar 用指定的名稱、默認(rèn)值、使用信息注冊(cè)一個(gè) time.Duration 類型 flag ,并將 flag 的值保存到 p 指向的變量。
2.25 func Var
func Var(value Value, name string, usage string)
Var 方法使用指定的名字、使用信息注冊(cè)一個(gè) flag 。該 flag 的類型和值由第一個(gè)參數(shù)表示,該參數(shù)應(yīng)實(shí)現(xiàn)了 Value 接口。例如,用戶可以創(chuàng)建一個(gè) flag ,可以用 Value 接口的 Set 方法將逗號(hào)分隔的字符串轉(zhuǎn)化為字符串切片。
2.26 func Set
func Set(name, value string) error
設(shè)置已注冊(cè)的 flag 的值。
2.27 func Parse
func Parse()
從 os.Args[1:] 中解析注冊(cè)的 flag 。必須在所有 flag 都注冊(cè)好而未訪問(wèn)其值時(shí)執(zhí)行。未注冊(cè)卻使用 flag -help 時(shí),會(huì)返回 ErrHelp 。
2.28 func Parsed
func Parsed() bool
返回是否 Parse 已經(jīng)被調(diào)用過(guò)。
2.29 func Visit
func Visit(fn func(*Flag))
按照字典順序遍歷標(biāo)簽,并且對(duì)每個(gè)標(biāo)簽調(diào)用 fn 。 這個(gè)函數(shù)只遍歷解析時(shí)進(jìn)行了設(shè)置的標(biāo)簽。
2.30 func VisitAll
func VisitAll(fn func(*Flag))
按照字典順序遍歷標(biāo)簽,并且對(duì)每個(gè)標(biāo)簽調(diào)用 fn 。 這個(gè)函數(shù)會(huì)遍歷所有標(biāo)簽,不管解析時(shí)有無(wú)進(jìn)行設(shè)置。
3. 代碼示例
3.1 解析 flag 參數(shù)為指針
package mainimport ("flag""fmt"
)// 定義命令行參數(shù)
var mode = flag.String("mode", "", "process mode")
var num = flag.Int("num", 5, "process number")
var isProcess = flag.Bool("isProcess", true, "process bool")func main() {// 未解析時(shí)查看已設(shè)置的 flag 數(shù)量registerNum := flag.NFlag()fmt.Printf("Before Parse registerNum is %#v\n", registerNum)// Before Parse registerNum is 0// 解析命令行參數(shù)flag.Parse()registerNum = flag.NFlag()fmt.Printf("After Parse registerNum is %#v\n", registerNum)// After Parse registerNum is 3// 無(wú)法進(jìn)行flag匹配的有哪些參數(shù)flagArgs := flag.Args()fmt.Printf("flagArgs is %#v\n", flagArgs)// 輸出命令行參數(shù)fmt.Println(*mode) // 必須加 * 號(hào)fmt.Println(*num)fmt.Println(*isProcess)
}
運(yùn)行結(jié)果:
wohu@wohu:~/GoCode/src/task$ go run main.go --mode "hello" --num 10 --isProcess=0
Before Parse registerNum is 0
After Parse registerNum is 3
flagArgs is []string{}
hello
10
false
wohu@wohu:~/GoCode/src/task$ ^C
3.2 解析 flag 參數(shù)為變量
package mainimport ("flag""fmt"
)func main() {// 定義命令行參數(shù)var mode stringvar num intvar isProcess bool// flag.StringVar這樣的函數(shù)第一個(gè)參數(shù)換成了變量地址,后面的參數(shù)和flag.String是一樣的flag.StringVar(&mode, "mode", "", "process mode")flag.IntVar(&num, "num", 5, "process number")flag.BoolVar(&isProcess, "isProcess", true, "process bool")// 解析命令行參數(shù)flag.Parse()// 輸出命令行參數(shù)fmt.Println("mode is ", mode)fmt.Println("num is ", num)fmt.Println("isProcess is ", isProcess)
}
flag.StringVar 和 flag.String 的區(qū)別:
flag.StringVar函數(shù)第一個(gè)參數(shù)為變量地址,該變量需要提前聲明,其余參數(shù)和flag.String是一樣的;flag.StringVar第一個(gè)參數(shù)就是變量的實(shí)際值,可以直接使用,而flag.String返回的是一個(gè)指針地址,使用的時(shí)候需要加 * 標(biāo)記;
其它 flag.xxx 和 flag.xxxVar 的區(qū)別和上面所說(shuō)的一樣。
3.3 自定義 flag 參數(shù)
使用 flag.var() 可以把自定義的數(shù)據(jù)類型作為參數(shù)值的類型,核心在于自定義的數(shù)據(jù)類型需要實(shí)現(xiàn)Value接口。
package mainimport ("errors""flag""fmt""strconv""strings"
)type Student struct {Name stringAge int
}func (s *Student) String() string {return fmt.Sprintf("Name: %s, Age: %d\n", s.Name, s.Age)
}func (s *Student) Set(_s string) error {studentArr := strings.Split(_s, ",")if len(studentArr) == 2 {s.Name = studentArr[0]s.Age, _ = strconv.Atoi(studentArr[1])return nil}return errors.New("error")
}func main() {name := flag.String("name", "admin", "user name")s := new(Student)flag.Var(s, "student", "student info")flag.Parse()fmt.Println("hello,", *name)fmt.Println(s)
}
執(zhí)行結(jié)果:
wohu@wohu:~/GoCode/src$ go run demo.go -name "wohu" -student "wohu",20
hello, wohu
Name: wohu, Age: 20wohu@wohu:~/GoCode/src$
總結(jié)
以上是生活随笔為你收集整理的Go 学习笔记(45)— Go 标准库之 flag(命令行参数解析)的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 隐形眼镜一副多少钱?
- 下一篇: Go 学习笔记(46)— Go 标准库之