• Golang flag包使用详解(一)


    概述

    flag包提供了一系列解析命令行参数的功能接口

    命令行语法

    命令行语法主要有以下几种形式

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

    以上语法对于一个或两个‘-’号,效果是一样的,但是要注意对于第三种情况,只支持非bool类型,原因是碰到如下情况时

    cmd -x *
    

    *为0,false有可能表示一个文件名或文件,也有可能表示x标签的值为0或false,会产生二义性,因此规定第三种只支持非bool类型。对于整形flag,合法的值可以为12340664,0x1234或负数等。对于布尔型flag,可以为10tfTF,truefalseTRUEFALSETrueFalse

    命令行参数解析方法

    使用flag主要包括以下几步

    1. 定义flag参数,有三种方式

      • 通过flag.String(), Bool(), Int() 等flag.Xxx()方法,该种方式返回一个相应的指针

        import "flag"
        var ip = flag.Int("flagname", 1234, "help message for flagname")
        
      • 通过flag.XxxVar()方法将flag绑定到一个变量,该种方式返回值类型,如

        var flagvar int
        func init() {
            flag.IntVar(&flagvar, "flagname", 1234, "help message for flagname")
        }
        
      • 通过flag.Var()绑定自定义类型,自定义类型需要实现Value接口(Receives必须为指针),如

        flag.Var(&flagVal, "name", "help message for flagname")
        

        对于这种类型的flag,默认值为该变量类型的初始值

    2. 调用flag.Parse()解析命令行参数到定义的flag

      flag.Parse()
      

      解析函数将会在碰到第一个非flag命令行参数时停止,非flag命令行参数是指不满足命令行语法的参数,如命令行参数为cmd --flag=true abc则第一个非flag命令行参数为“abc”

    3. 调用Parse解析后,就可以直接使用flag本身(指针类型)或者绑定的变量了(值类型)

      fmt.Println("ip has value ", *ip)
      fmt.Println("flagvar has value ", flagvar)
      

      还可通过flag.Args()flag.Arg(i)来获取非flag命令行参数

    4. 如果需要每个函数的详细demo,可参见Gopkg:flag

    示例

    • 示例1: 获取“species” flag的值,默认为“gopher”

      var species = flag.String("species", "gopher", "the species we are studying")
      
    • 示例2: 两个flag共享同一个变量,一般用于同时实现完整flag参数和对应简化版flag参数,需要注意初始化顺序和默认值

      var gopherType string
      
      func init() {
        const (
          defaultGopher = "pocket"
          usage         = "the variety of gopher"
        )
        flag.StringVar(&gopherType, "gopher_type", defaultGopher, usage)
        flag.StringVar(&gopherType, "g", defaultGopher, usage+"(shorthand)")
      }
      
    • 示例3: 将flag绑定用户自定义类型。按我们先前所说,只需要实现Value接口,但实际上,如果需要取值的话,需要实现Getter接口,看下接口定义就明白了:

      type Getter interface {
        Value
        Get(string) interface{}
      }
      type Value interface {
        String() string
        Set(string) error
      }
      

      接下来,我们实现一个解析并格式化命令行输入的时间集合的例子,如下

      package main
      
      import (
        "errors"
        "flag"
        "fmt"
        "strings"
        "time"
      )
      
      type interval []time.Duration
      
      //实现String接口
      func (i *interval) String() string {
        return fmt.Sprintf("%v", *i)
      }
      
      //实现Set接口,Set接口决定了如何解析flag的值
      func (i *interval) Set(value string) error {
          //此处决定命令行是否可以设置多次-deltaT
        if len(*i) > 0 {
          return errors.New("interval flag already set")
        }
        for _, dt := range strings.Split(value, ",") {
          duration, err := time.ParseDuration(dt)
          if err != nil {
            return err
          }
          *i = append(*i, duration)
        }
        return nil
      }
      
      var intervalFlag interval
      
      func init() {
        flag.Var(&intervalFlag, "deltaT", "comma-separated list of intervals to use between events")
      }
      
      func main() {
        flag.Parse()
        fmt.Println(intervalFlag)
      }
      

      运行结果:

      //./commandLine -deltaT 61m,72h,80s
      [1h1m0s 72h0m0s 1m20s]
  • 相关阅读:
    linux下的磁盘挂载
    shell中的循环语句while
    hadoop安装和配置
    shell 命令 创建/删除 软连接 ln -s
    azkaban disable 停用部分工作流
    git dev 分支merge到master
    shell 命令 zip unzip
    git代码同步服务器代码需要注意的问题
    shell 命令 if elif else fi 用法
    python 引入本地 module
  • 原文地址:https://www.cnblogs.com/lvdongjie/p/6554462.html
Copyright © 2020-2023  润新知