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