golang-flag命令行参数的简单介绍

介绍

在写命令行程序(工具、server)时,对命令参数进行解析是常见的需求。各种语言一般都会提供解析命令行参数的方法或库,以方便程序员使用。在 go 标准库中提供了一个包:flag,方便进行命令行解析。

概述


定义flags
  • 标准定义
    (1)flag.Type(name, defValue, usage)
    其中Type为String, Int, Bool等;并返回一个相应类型的指针。
    示例:
    var ip = flag.Int("flagname", 1234, "help message for flagname")
    (2)flag.TypeVar(&flagvar, name, defValue, usage)
    将flag绑定在flagvar变量上。
    示例:
    var newflag int
    flag.IntVar(&newflag, "flagname", 1234, "help message for flagname")
    
  • 自定义flag
    flag.Var(&flagvar, name, usage)
    这种方法要实现flag.Value接口:
    type Value interface {
      String() string
      Set(string) error
    }
    
    示例:
    type percentage float32
    func (p *percentage) Set(s string) error {
      v, err := strconv.ParseFloat(s, 32)
      *p = percentage(v)
      return err
    }
    func (p *percentage) String() string { return fmt.Sprintf("%f", *p) }
    
    var pip percentage
    flag.Var(&pop,"pop","popularity")
    
解析flag

在所有的 flag 定义完成之后,可以通过调用 flag.Parse() 进行解析。
命令行 flag 的语法有如下三种形式:

-flag // 只支持bool类型
-flag=x
-flag x // 只支持非bool类型

其中第三种形式只能用于非 bool 类型的 flag,默认的,提供了 -flag,则对应的值为 true,否则为 flag.Bool/BoolVar 中指定的默认值;如果希望显示设置为 false 则使用 -flag=false。

int 类型可以是十进制、十六进制、八进制甚至是负数;bool 类型可以是1, 0, t, f, true, false, TRUE, FALSE, True, False。Duration 可以接受任何 time.ParseDuration 能解析的类型。

主要类型的方法

flag 包中主要是FlagSet类型。

  • 实例化方式
    NewFlagSet() 用于实例化 FlagSet。预定义的 FlagSet 实例 CommandLine 的定义方式:
    // The default set of command-line flags, parsed from os.Args.
    var CommandLine = NewFlagSet(os.Args[0], ExitOnError)
    
    可见,默认的 FlagSet 实例在解析出错时会退出程序。由于 FlagSet 中的字段没有 export,其他方式获得 FlagSet实例后,比如:FlagSet{} 或 new(FlagSet),应该调用Init() 方法,以初始化 name 和 errorHandling,否则 name 为空,errorHandling 为 ContinueOnError。
  • 解析参数
    从参数列表中解析定义的 flag。方法参数 arguments 不包括命令名,即应该是os.Args[1:]。Parse(arguments []string)的源码如下:
    func (f *FlagSet) Parse(arguments []string) error {
        f.parsed = true
        f.args = arguments
        for {
            seen, err := f.parseOne()
            if seen {
                continue
            }
            if err == nil {
                break
            }
            switch f.errorHandling {
            case ContinueOnError:
                return err
            case ExitOnError:
                os.Exit(2)
            case PanicOnError:
                panic(err)
            }
        }
        return nil
    }
    
    真正解析参数的方法是非导出方法 parseOne。其解析停止的条件如下:
    (1)第一个为non-flag参数
    当遇到单独的一个"-“或不是”-"开始时,会停止解析。
    s := f.args[0]
    if len(s) == 0 || s[0] != '-' || len(s) == 1 {
          return false, nil
    }
    
    示例:./nginx - -c 或 ./nginx build -c,这两种情况,-c 都不会被正确解析。像该例子中的"-“或build(以及之后的参数),我们称之为 non-flag 参数。
    (2)两个连续的“–”
    当遇到连续的两个”-"开始时,解析停止。
    if s[1]  == '-' {
        num_minuses++
        if len(s) == 2 { // "--" terminates the flags
            f.args = f.args[1:]
            return false, nil
        }
    }
    
    其中,f.args = f.args[1:]表示每执行成功一次 parseOne,f.args 会少一个。所以,FlagSet 中的 args 最后留下来的就是所有 non-flag 参数。
  • 常见方法
    Arg(i int) 和 Args() 这两个方法就是获取 non-flag 参数的;NArg()获得 non-flag 的个数;NFlag() 获得 FlagSet 中的actual长度(即被设置了的参数个数)。

参考链接

https://www.cnblogs.com/landv/p/11114508.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值