flag
包实现了命令行参数的解析。
命令行选项格式
flag
库支持三种命令行选项格式。
-
和--
都可以使用,它们的作用是一样的。
第一种形式只支持布尔类型的选项,出现即为true
,不出现为默认值。 第三种形式不支持布尔类型的选项。因为这种形式的布尔选项在类 Unix 系统中可能会出现意想不到的行为。
接收参数
flag.Type 的方式
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
| package main
import ( "flag" "fmt" )
var ( stringflag *string intflag *int boolflag *bool )
func init() { stringflag = flag.String("stringflag", "default", "提示: stringflag") intflag = flag.Int("intflag", 10, "提示: intflag") boolflag = flag.Bool("boolflag", false, "提示: boolflag") }
func main() { flag.Parse()
fmt.Println("int flag:", *intflag) fmt.Println("bool flag:", *boolflag) fmt.Println("string flag:", *stringflag) }
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
| ➜ go build -o main -v main.go
➜ ./main int flag: 10 bool flag: false string flag: default
➜ ./main -stringflag=han -intflag=10 -boolflag int flag: 10 bool flag: true string flag: han
➜ ./main -h Usage of ./main: -boolflag 提示: boolflag -intflag int 提示: intflag (default 10) -stringflag string 提示: stringflag (default "default")
|
flag.TypeVar方式
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
| package main
import ( "flag" "fmt" )
var ( stringflag string intflag int boolflag bool )
func init() { flag.StringVar(&stringflag, "stringflag", "default", "提示: stringflag") flag.IntVar(&intflag, "intflag", 10, "提示: intflag") flag.BoolVar(&boolflag, "boolflag", false, "提示: boolflag") }
func main() { flag.Parse()
fmt.Println("int flag:", intflag) fmt.Println("bool flag:", boolflag) fmt.Println("string flag:", stringflag) }
|
输出和 flag.Type
的方式是一样的。
flag.Var 方式
flag.Var
这种方式需要实现 flag.Value
接口
1 2 3 4
| type Value interface { String() string Set(string) error }
|
简单使用
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33
| package main
import ( "flag" "fmt" "strings" )
type List []string
func (l *List) String() string { return fmt.Sprintf("%v", *l) }
func (l *List) Set(s string) error { split := strings.Split(s, ",") *l = split return nil }
var l List
func init() { flag.Var(&l, "list", "长标记-列表,用英文逗号分割") flag.Var(&l, "l", "短标记-列表,用英文逗号分割") }
func main() { flag.Parse() fmt.Printf("listi s %v \n", l) }
|
执行
1 2 3 4 5 6 7 8 9 10 11 12
| ➜ ./main -list=one,two,three listi s [one two three]
➜ ./main -l=name,age,addr listi s [name age addr]
➜ ./main- h Usage of ./main: -l value 短标记-列表,用英文逗号分割 -list value 长标记-列表,用英文逗号分割
|
解析程序中的字符串
有时候选项并不是通过命令行传递的。例如,从配置表中读取或程序生成的。这时候可以使用flag.FlagSet
结构的相关方法来解析这些选项。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| package main
import ( "flag" "fmt" )
func main() { myFlagSet := flag.NewFlagSet("myFlag", flag.ExitOnError)
args := []string{"-intflag", "12", "-stringflag", "test"} intflag := myFlagSet.Int("intflag", 10, "提示: intflag") stringflag := myFlagSet.String("stringflag", "default", "提示: stringflag") myFlagSet.Parse(args)
fmt.Printf("stringflag的值是 %v \n", *stringflag) fmt.Printf("intflag的值是 %v \n", *intflag) }
|
1 2 3
| ➜ ./main stringflag的值是 test intflag的值是 12
|
几个常用的数据结构
错误相关
1 2 3 4 5 6 7
| type ErrorHandling int
const ( ContinueOnError ErrorHandling = iota ExitOnError PanicOnError )
|
Flag类型代表一条flag的状态。
1 2 3 4 5 6
| type Flag struct { Name string Usage string Value Value DefValue string }
|
FlagSet代表一个已注册的flag的集合。FlagSet零值没有名字,采用ContinueOnError错误处理策略。
1 2 3 4 5 6 7 8 9 10
| type FlagSet struct { Usage func() name string parsed bool actual map[string]*Flag formal map[string]*Flag args []string errorHandling ErrorHandling output io.Writer }
|