flag
命令行语法
命令行语法主要有以下几种形式
-flag //只支持bool类型(加上该参数,解析值为true)
-flag=x
-flag x //只支持非bool类型
以上语法对于一个或两个‘-’号,效果是一样的。
常用函数
- flag.String(), flag.Bool(), flag.Int(), flag.Float64() 返回对应类型的指针:
func Xxx(name string, value Xxx, usage string) *Xxx
arguments.IntPointer = flag.Int("int_pointer", 0, "help message for int_pointer")
arguments.StringPointer = flag.String("string_pointer", "", "help message for string_pointer")
arguments.FloatPointer = flag.Float64("float_pointer", 0.1, "help message for float_pointer")
arguments.BoolPointer = flag.Bool("bool_pointer", false, "help message for bool_pointer")
- flag.XxxVar() 将参数绑定到对应类型的指针:
func XxxVar(p *Xxx, name string, value Xxx, usage string)
flag.IntVar(&arguments.IntVariable, "int_variable", 0, "help message for int_variable")
flag.StringVar(&arguments.StringVariable, "string_variable", "", "help message for string_variable")
flag.Float64Var(&arguments.FloatVariable, "float_variable", 0.1, "help message for float_variable")
flag.BoolVar(&arguments.BoolVariable, "bool_variable", false, "help message for bool_variable")
- flag.Var() 绑定自定义类型:
func Var(value Value, name string, usage string
,自定义类型需要实现Value接口。Var定义了一个有指定名字和用法说明的标签。标签的类型和值是由第一个参数指定的,这个参数是Value类型,并且是用户自定义的实现了Value接口的类型。
type Value interface {
String() string
Set(string) error
}
- flag.Parse() 解析命令行参数到定义的flag
解析函数将会在碰到第一个非flag命令行参数时停止,非flag命令行参数是指不满足命令行语法的参数,如命令行参数为./selpg -s1 -e2 input.txt
则第一个非flag命令行参数为“input.txt”。
flag.Parse()
- flag.Args(),flag.Arg(i),flag.NArg()
// 在命令行标签被解析之后(遇到第一个非flag参数),flag.NArg()就返回解析后参数的个数。
fmt.Println(flag.NArg())
// flag.Args()返回非标签的命令行参数
for i, arg := range flag.Args() {
// flag.Arg(i)返回第i个命令行参数。
fmt.Printf("%s %s\n", flag.Arg(i), arg)
}
- flag.Usage() 输出命令行的提示信息
// 我们可以重定义Usage函数
flag.Usage = func () {
fmt.Println("**Some other message here**")
flag.PrintDefaults() // 默认提示信息
}
例子
package main
import (
"flag"
"fmt"
)
type Arguments struct{
IntVariable int
IntPointer *int
StringVariable string
StringPointer *string
FloatVariable float64
FloatPointer *float64
BoolVariable bool
BoolPointer *bool
}
var arguments Arguments
func init() {
flag.IntVar(&arguments.IntVariable, "int_variable", 0, "help message for int_variable")
arguments.IntPointer = flag.Int("int_pointer", 0, "help message for int_pointer")
flag.StringVar(&arguments.StringVariable, "string_variable", "", "help message for string_variable")
arguments.StringPointer = flag.String("string_pointer", "", "help message for string_pointer")
flag.Float64Var(&arguments.FloatVariable, "float_variable", 0.1, "help message for float_variable")
arguments.FloatPointer = flag.Float64("float_pointer", 0.1, "help message for float_pointer")
flag.BoolVar(&arguments.BoolVariable, "bool_variable", false, "help message for bool_variable")
arguments.BoolPointer = flag.Bool("bool_pointer", false, "help message for bool_pointer")
flag.Usage = usage
flag.Parse()
}
func usage() {
fmt.Println("**Some other message here**")
flag.PrintDefaults()
}
func main() {
fmt.Printf("There are %d non-flags:\n", flag.NArg())
for i, _ := range flag.Args() {
fmt.Printf("%s\n", flag.Arg(i))
}
fmt.Println("*******************")
fmt.Printf("IntVariable: %d\n", arguments.IntVariable)
fmt.Printf("IntPointer: %d\n", *arguments.IntPointer)
fmt.Printf("StringVariable: %s\n", arguments.StringVariable)
fmt.Printf("StringPointer: %s\n", *arguments.StringPointer)
fmt.Printf("FloatVariable: %f\n", arguments.FloatVariable)
fmt.Printf("FloatPointer: %f\n", *arguments.FloatPointer)
fmt.Printf("BoolVariable: %v\n", arguments.BoolVariable)
fmt.Printf("BoolPointer: %v\n", *arguments.BoolPointer)
}
// 测试如下:
λ .\flag.exe -int_variable=1 -string_pointer "str" -float_pointer 1.0 non-flag -bool_variable
There are 2 non-flags:
non-flag
-bool_variable
*******************
IntVariable: 1
IntPointer: 0
StringVariable:
StringPointer: str
FloatVariable: 0.100000
FloatPointer: 1.000000
BoolVariable: false
BoolPointer: false
λ .\flag.exe -int_variable=1 -string_pointer"str" -float_pointer 1.0 -bool_variable
flag provided but not defined: -string_pointerstr
**Some other message here**
-bool_pointer
help message for bool_pointer
-bool_variable
help message for bool_variable
-float_pointer float
help message for float_pointer (default 0.1)
-float_variable float
help message for float_variable (default 0.1)
-int_pointer int
help message for int_pointer
-int_variable int
help message for int_variable
-string_pointer string
help message for string_pointer
-string_variable string
help message for string_variable
自定义参数类型:
package main
import (
"errors"
"fmt"
"flag"
"strings"
"strconv"
)
type MySlice []int
/**
* 实现Value接口
* - String() string
* - Set(string) error
*/
func (mySlice *MySlice) String() string {
return fmt.Sprintf("%v", *mySlice)
}
func (mySlice *MySlice) Set(value string) error {
if len(*mySlice) > 0 {
return errors.New("MySlice has already been set!")
}
for _, numStr := range strings.Split(value, ",") {
num, err := strconv.Atoi(numStr)
if err == nil {
*mySlice = append(*mySlice, num)
} else {
return errors.New("Your input has some non-integers")
}
}
return nil
}
var mySlice MySlice
func init() {
flag.Var(&mySlice, "slice", "a slice of some integers")
flag.Parse()
}
func main() {
fmt.Println(mySlice)
}
// 测试如下:
λ .\flag.Var.exe -slice 2,3,1
[2 3 1]
pflag
pflag是Go flag包的一个替代插件,实现了POSIX / GNU风格的flag,基本使用于"flag"包基本相同。
安装
go get github.com/spf13/pflag
参数解析
- 默认参数以
--
作为前缀:
--flag # 只支持bool类型
--flag=x
--flag x # 只支持非bool类型
pflag包还定义了一些不在flag中的新函数,这些函数为flag提供了一个字母的缩写。可以通过将“P”附加到定义标志的任何函数的名称上来使用它们。
var ip = flag.IntP("flagname", "f", 1234, "help message")
var flagvar bool
func init() {
flag.BoolVarP(&flagvar, "boolname", "b", true, "help message")
}
flag.VarP(&flagVal, "varname", "v", "help message")
此时,参数也可以以-
为前缀:
-flag # 只支持bool类型
-flag=x
-flag x # 只支持非bool类型
-flagx # 只支持非bool类型
结束符--
后标志解析停止。与flag包不同,flag可以在这个结束符之前的命令行中的任何地方散布参数。
Integer标志接受1234、0664、0x 1234,并且可以是负数。Boolen标志接受1,0,t, f, true, false, TRUE, FALSE, True, False。Duration标志接受任何符合time.ParseDuration的输入。
设置非必须选项的默认值
var ip = flag.IntP("flagname", "f", 1234, "help message")
flag.Lookup("flagname").NoOptDefVal = "4321"
Parsed Arguments | Resulting Value |
---|---|
–flagname=1357 | ip=1357 |
–flagname | ip=4321 |
[nothing] | ip=1234 |
其他新增方法详见源码。