Overview

flag包实现了命令行的解析

使用说明(Usage)

定义flags使用flag.Bool(),String(),Int()等 这个声明一个整型flag,-flagname存储在类型为*int的整型指针ip中
import "flag"
var ip = flag.Int("flagname", 1234, "help message for flagname")

可以将值绑定到变量中,使用Var()函数

import "flag"
var flagint int
func init() {
    flag.IntVar(&flagvar, "flagname", 1234, "help message for flagname")
}

或者可以创建满足值接口(接受者为指针)的自定义flag,并可以通过flag词法分析联合

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

对于这种flags,默认值是变量的初始值,在定义完所有flags,调用

flag.Parse()
解析命令行参数到定义的flags 在解析完flags后,参数在flag.Args()返回的切片中可用或使用个体flag.Arg(i),参数索引从0到flag.NArg()-1

命令行flag语法

允许的格式如下:
-flag
-flag=x
-flag x // 只有non-boolean flag允许

可以使用一个或两个负号,它们是等价的,最后一种形式对于boolean flag是不被允许的,因为下列命令行的意义:

cmd -x*

*是Unix Shell的通配符,如果这是个0,false等命名的文件,则会造成歧义,所有,必须使用-flag=false来关闭boolean flag Falg停止解析直到出现non-flag参数(“-“是一种non-flag参数)或在”–“终结 Integer flag接受1234,0664,0x1234和负数,Boolean flag接受如下:

1,0,t,f,true,false,TRUE,FALSE,True,False

Duration flag接受对于time.ParseDuration合理的输入 默认的命令行的flag集合是由高层函数控制,FlagSet类型允许定义独立的flag集合,比如实现命令行接口的子命令,FlagSet方法和默认命令行flag集合的高层函数是类似的

变量(Variables)

CommandLine是默认命令行flags集合,由os.Args解析,顶层的函数比如:BoolVar,Arg等都是CommandLine方法的封装
var CommandLine = NewFlagSet(os.Args[0], ExitOnError)

ErrHelp是-h或-help flag触发,但是没有定义这种flag返回的错误

var ErrHelp = errors.New("flag: help requestd")

Usage打印一个关于所用flag用法的用法消息到命令行输出,默认是os.Stderr,当解析flag发生错误时会被调用,该函数是一个变量可以指向自定义函数,默认是打印简单的头部和调用PrintDefaults 关于输出格式的细节和如何控制它,查看PrintDefaults的文档,自定义的usage函数可能选择退出程序,默认情况下,退出无论如何都会发生,因为命令行错误处理策略是ExitOnError

var Usage = func() {
    fmt.Fprintf(CommandLine.Output(), "Usage of %s:\n", os.Args[0])
    PrintDefaults()
}

函数(Functions)

func Arg(i int) string

Arg返回第i个命令行参数,Arg(0)在flags处理后返回第一个剩下的参数,Arg返回空字符串,如果要求的元素不存在

func Args() []string

Args返回non-flag命令行参数

func Bool(name string, value bool, usage string) *bool

Bool定义一个指定名称的boolean flag,默认值和usage,返回值是储存flag value的地址

func BoolVar(p *bool, name string, value bool, usage string)

BoolVar定义一个指定名称的boolean flag,默认值和usage,flag value存储在传递的p中

func Duration(name string, value time.Duration, usage string) *time.Duration

Duration定义一个指定名称的duration flag,默认值和usage,返回值是储存flag value的地址 flag接受time.ParseDuration可接受的值

func DurationVar(p *time.Duration, name string, value time.Duration, usage string)

DurationVar定义一个指定名称的duration flag,默认值和usage,flag value存储在p中

func Float64(name string, value float64, usage string) *float64

Float64定义一个指定名称的float64 flag,默认值和usage,返回存储flag value的地址

func Float64Var(p *float64, name string, value float64, usage string)

Float64Var定义一个指定名称的float64 flag,默认值和usage,flag value存储在p中

func Int(name string, value int, usage string) *int

Int定义一个指定名称的int flag,默认值和usage,返回存储flag value的地址

func Int64(name string, value int64, usage string) *int64

Int64定义一个指定名称的int64 flag,默认值和usage,返回存储flag value的地址

func IntVar(p *int, name string, value int, usage string)

IntVar定义一个指定名称的int flag,默认值和usage,flag value存储在p中

func Int64Var(p *int64, name string, value int64, usage string)

Int64Var定义一个指定名称的int64 flag,默认值和usage,flag value存储在p中

func NArg() int

NArg返回flag处理后剩下的参数数量

func NFlag() int

NFlag返回command-line设置的flag数量

func Parse()

Parse解析命令行从os.Args[1:],必须在所有flags定义之后,flags能够被访问之前调用

func Parsed() bool

调查是否Parse过

func PrintDefaults()

PrintDefaults打印到标准错误输出一个默认设置由定义的command-line flag展示usage message,除非另行配置,对于一个整型flag x,默认有以下形式:
-x int
    usage-message-for-x (default 7)

描述信息将会出现在分割的行除了一个字节名称的bool flag,对于bool flags,这种类型将会被忽略且如果名称是一个字节,usage message出现在同一行,括号默认被忽略如果默认是该类型的零值,被列出的类型,这int能够被改变通过放置反引号名称在flags的usage string中,第一个这种项目在message中被带到参数名展示在消息中且反引号在展示时会被去掉 比如,给出:

flag.String("l", "", "search `directory` for include files")

输出将会是:

-l directory
    search directory for include files

为了改变flag messages的目的地,调用CommandLine.SetOutput

func Set(name string, value string) error

设置command-lien flag值

func String(name string, value string, usage string) *string

String定义一个指定名字的string flag,默认值和usage,返回flag value的地址

func StringVar(p *string, name string, value string, usage string)

StringVar定义一个指定名字的string flag,默认值和usage,flag value存储在p中

func Uint(name string, value uint, usage string) *uint

Uint定义一个指定名字的uint flag,默认值和usage,返回flag value的地址

func Uint64(name string, value uint64, usage string) *uint64

Uint64定义一个指定名字的uint64 flag,默认值和usage,返回flag value的地址

func Uint64Var(p *uint64, name string, value string, usage string)

Uint64Var定义一个指定名字的uint64 flag,默认值和usage,flag value存储

func UintVar(p *uint, name string, value uint, usage string)

UintVar定义一个指定名字的uint flag,默认值和usage,flag value存储在p中

func UnquoteUsage(flag *Flag) (name string, usage string)

UnquoteUsage提取反引号名称从flag的usage string并且返回未反引的usage.给出"a `name` to show"返回("name", "a name to show"),如果不存在反引号,名称是对flag value类型的有根据猜测或者是空字符串,如果flag是boolean

func Var(value Value, name string, usage string)

Var定义一个指定名字的flag和usage string,类型通过第一个参数呈现,value类型,典型是用户定义Value的实现,比如,调用者能够创建一个flag转换逗号分隔的字符串成分割的切片,通过给出Value的slice方法,特别是,Set能分割逗号分隔的字符串到切片中

func Visit(fn func(*Flag))

Visit以字典序访问命令行flag,对其调用fn,只访问被设置的flag

func VisitAll(fn func(*Flag))

VisitAll以字典序遍历所有flag,对其调用fn,包括未被设置的flag

ErrorHandling定义了如果FlagSet.Parse出错的行为

type ErrorHandling int

如果FlagSet解析失败,这些常量将会描述其行为

const (
    ContinueOnError ErrorHandling = itoa // 返回描述性错误
    ExitOnError // 调用os.Exit(2)
    PanicError // 通过描述性错误调用panic
)

type Flag

Flag用于呈现flag的状态

type Flag struct {
    Name string //出现在命令行中的名字
    Usage string // 帮助信息
    Value Value // 设置的值
    DefValue string // 为usage message,default value(as text)
}

func Lookup(name string) *Flag

返回命名的命令行flag的Flag结构体,返回空如果不存在

type FlagSet

FlagSet呈现一个定义的flags集合,FlagSet的零值是没有名字且有ContinueOnError错误处理
type FlagSet struct {
    /*
        Usage当flag解析错误时调用,默认错误处理是ExitOnError
    */
    Usage() func()
    // contains filtered or unexported fields
}

func NewFlagSet(name string, errorHandling ErrorHandling) *FlagSet

NewFlagSet返回一个新的指定名字和错误处理属性的FlagSet,如果name非空,默认将会被打印在usage message和错误消息中

func (*FlagSet) ErrorHandling() ErrorHandling

返回FlagSet的ErrorHandling

func (*FlagSet) Init(name string, errorhanding ErrorHandling)

设置FlagSet的名称和错误处理

func (*FlagSet) Name() string

返回FlagSet的名称

func (f *FlagSet) Output() io.Writer

返回usage message和错误信息的目的地,如果Output未被设置或设为ni,返回os.Stderr

func (f *FlagSet) Parse(arguments []string)

Parse解析不应该包含命令名称的flag定义,必须在FlagSet定义之后,程序访问flags之前调用,如果-help或-h被设置但没被定义,将会返回ErrHelp

type Getter

Getter是一个接口允许值的内容能够被取回,它封装了Value接口,而不是成为其一部分,是由于兼容的原因,该包提供的所有Value类型都符合Getter接口
type Getter interface {
    Value
    Get() interface{}
}

type Value

Value是一个接口对于储存在flag的动态值(默认值被呈现为string) 如果Value有IsBoolFlag() bool 方法返回true,则命令行解析器使得-name和-name=true等价,而不是下一个命令行参数 Set被调用一次,命令行参数顺序对于每个存在的flag,flag包可能调用String()使用nil pointer接收者
type Value interface {
    String() string
    Set(string) error
}

Example


// var.go
// example run by: go run var.go -species=hello -g=smart -deltaT=10s,15s
package main

import (
	"flag"
	"fmt"
	"time"
	"errors"
	"strings"
)
// a single flag with name "species", default value: "gopher" and usage message
var species = flag.String("species", "gopher", "the species we are studying")
// a variable shared with two flag to support multi name flag
var gopherType string
// use-defined type used to flag value
type interval []time.Duration
func (i *interval) String() string {
	return fmt.Sprint(*i)
}
func (i *interval) Set(value string) error {
	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-spreaded list of intervals to use between events")
}
func init() {
	const (
		defaultGopher = "pocket"
		usage = "the variety of gopher"
	)
	flag.StringVar(&gopherType, "gopher_type", defaultGopher, usage)
	flag.StringVar(&gopherType, "g", defaultGopher, usage)
}
func main() {
	flag.Parse()
	fmt.Println(*species)
	fmt.Println(gopherType)
	fmt.Println(intervalFlag.String())
}