介绍

  1. 编写命令行程序时,需要对命令参数进行解析。
  2. 在Go语言中的 flag 包中,提供了命令行参数解析的功能,以下为支持的参数类型:


flag 参数 有效值
string 合法字符串
int、int64、uint、uint64 1234、0664、0x1234 等类型,也可以是负数
float64 合法浮点数
bool 1、0、t、f、T、F、true、false、TRUE、FALSE、True、False
duration 任何合法的时间段字符串,如“300ms”、“-1.5h”、“2h45m”,
合法的单位有“ns”、“us”、“µs”、“ms”、“s”、“m”、“h”

使用

flag.Type()

介绍

Type 可以是上面类型表格中的类型,返回值为对应类型的指针。

  1. flag.Type(flag 名, 默认值, 帮助信息) *Type

示例
  1. name := flag.String("name", "张三", "姓名")
  2. age := flag.Int("age", 18, "年龄")
  3. married := flag.Bool("married", false, "婚否")
  4. delay := flag.Duration("d", 0, "时间间隔")

flag.TypeVar()

介绍

Type 可以是上面类型表格中的类型,其功能为将 flag 绑定到对应类型的指针上。

  1. flag.TypeVar(Type 指针, flag 名, 默认值, 帮助信息)

示例
  1. var name string
  2. flag.StringVar(&name, "name", "张三", "姓名")
  3. var age int
  4. flag.IntVar(&age, "age", 18, "年龄")
  5. var married bool
  6. flag.BoolVar(&married, "married", false, "婚否")
  7. var delay time.Duration
  8. flag.DurationVar(&delay, "d", 0, "时间间隔")

flag.Parse()

通过以上两种方法定义好命令行 flag 参数后,需要通过调用 flag.Parse() 来对命令行参数进行解析。

支持的命令行参数格式有以下几种:

-flag=x 支持所有类型 (推荐)
-flag:x 只支持 bool 类型
-flag x 只支持非 bool 类型
  1. package main
  2. import (
  3. "flag"
  4. "fmt"
  5. )
  6. var Input_pstrName = flag.String("name", "gerry", "input ur name")
  7. var Input_piAge = flag.Int("age", 20, "input ur age")
  8. var Input_flagvar int
  9. func Init() {
  10. flag.IntVar(&Input_flagvar, "flagname", 1234, "help message for flagname")
  11. }
  12. func main() {
  13. Init()
  14. flag.Parse()
  15. fmt.Println("name=", *Input_pstrName)
  16. fmt.Println("age=", *Input_piAge)
  17. fmt.Println("flagname=", Input_flagvar)
  18. }

运行:

  1. $ go run main.go -name "aaa" -age=123 -flagname=999
  2. name= aaa
  3. age= 123
  4. flagname= 999

flag.Var()

我们还可以创建自定义 flag,只要实现 flag.Value 接口即可,这时候可以通过如下方式定义该 flag:

  1. flag.Var(value Value, name string, usage string)
  2. flag.Var(&flagVal, "name", "help message for flagname")

示例
  1. package main
  2. import (
  3. "flag"
  4. "fmt"
  5. "strings"
  6. )
  7. /*
  8. Value接口:
  9. type Value interface {
  10. String() string
  11. Set(string) error
  12. }
  13. 实现flag包中的Value接口,将命令行接收到的值用,分隔存到slice里
  14. */
  15. type sliceValue []string
  16. func newSliceValue(vals []string, p *[]string) *sliceValue {
  17. *p = vals
  18. return (*sliceValue)(p)
  19. }
  20. func (s *sliceValue) Set(val string) error {
  21. *s = strings.Split(val, ",")
  22. return nil
  23. }
  24. //flag为slice的默认值default is me,和return返回值没有关系
  25. func (s *sliceValue) String() string {
  26. *s = strings.Split("default is me", ",")
  27. return "It's none of my business"
  28. }
  29. /*
  30. 可执行文件名 -slice="java,go" 最后将输出[java,go]
  31. 可执行文件名 最后将输出[default is me]
  32. */
  33. func main(){
  34. var languages []string
  35. flag.Var(newSliceValue([]string{}, &languages), "slice", "I like programming `languages`")
  36. flag.Parse()
  37. //打印结果slice接收到的值
  38. fmt.Println(languages)
  39. }

通过-slice go,php这样的形式传递参数,languages 得到的就是 [go, php],如果不加-slice参数则打印默认值[default is me]

  1. $ go run main.go -slice go,php,java
  2. [go php java]

flag 中对 Duration 这种非基本类型的支持,使用的就是类似这样的方式,即同样实现了 Value 接口