Golang | Stdlib: Flag 学习笔记
Contents
flag 包学习笔记概要:
- 如何定义命令行参数,即 flags ?
- flags 解析规则及语法格式 ?
- flag 包有哪些重要的变量、函数以及类型 ?
- 如何绑定用户自定义的数据类型作为参数值的类型?
1. Flag
Flag
:解析命令行参数,其实现方法是将命令行标志与程序中的某一变量进行绑定,开发人员使用变量在程序中进行逻辑处理。
2. 定义flags
有三种方式定义 flags
2.1. 方式一
通过 flag.Type(name, defValue, usage) *Type {}
方法,该方法返回一个对应数据类型的指针, 其中 Type 为:String、Int、Bool等。
|
|
2.2. 方式二
通过 flag.TypeVar(&flagvar, name, defValue, usage) Type {}
方法将flag绑定到一个变量, 该方法返回结果为值类型
|
|
2.3. 方式三
通过 flag.Var()
方法绑定自定义类型,自定义类型需要实现Value接口(要求receiver是指针)
|
|
注:这种方式是没有提供默认值的,所以默认值就是类型的零值。(备注:具体如何实现自定义类型绑定会在后面介绍)
3. 命令行参数解析及语法格式
命令行参数定义好了,该如何解析呢?
3.1. 解析
在所有flag定义完成之后,调用 flag.Parse()
解析
- 对该函数的调用必须在所有命令参数存储载体的声明(即:上面对 num 和 port的声明)和设置(即: 上面调用
flag.IntVar()
) 之后,并且在读取任何命令参数值之前进行。正因为如此,我们最好把 flag.Parse() 放在 main 函数第一行. - 解析函数将会在碰到第一个
非 flag 命令行参数
时停止,非flag命令行参数是指不满足命令行语法的参数,如命令行参数为 cmd –flag=true abc 则第一个非flag 命令行参数为 “abc”
注:调用
Parse
解析后,就可以直接使用 flag 本身(指针类型)或者绑定的变量了(值类型), 还可通过 flag.Args(), flag.Arg(i) 来获取非flag命令行参数
3.2. 命令行语法
命令行语法格式:
|
|
注:布尔类型的参数防止解析时的二义性,应该使用等号的方式指定。
4. 变量、类型和函数
4.1. 变量
flag.ErrHelp:该错误类型用于当命令行指定了 –help 参数但没有定义时。
flag.Usage:这是一个函数,用于输出所有定义了的命令行参数和帮助信息(Usage Message)。 当命令行参数解析出错,该函数会被调用。我们可通过
flag.Usage = func() {}
指定自定义的Usage。- flag.Usage 的类型是func(),即一种无参数声明且无结果声明的函数类型
注意,对flag.Usage的赋值必须在调用 flag.Parse() 函数之前
- flag.CommandLine: 类型 flag.FlagSet 的实例, 相当于默认情况下的命令参数容器.
4.2. 函数
4.3. 类型
4.3.1. ErrorHandling
|
|
该类型定义了在参数解析出错时,处理错误定义的三个常量
|
|
4.3.2. FlagSet
FlagSet
是该包的核心结构
|
|
该类型同时提供了一系列的方法集合
<MethodSet>
, 通过这些方式来实现CLI的灵活处理
4.3.3. Flag
Flag
结构如下
|
|
4.3.4. Value
Value定义:
|
|
4.4. 主要类型的方法
4.4.1. 实例化方式:flag.NewFlagSet()
flag.NewFlagSet()
用于实例化 FlagSet。例如:预定义的 FlagSet实例 subCommand
的定义方式:
|
|
注:可用于定义子命令
- 由于FlagSet的字段没有 export,其他方式获得FlagSet的实例后,比如 FlagSet{}、new(FlagSet), 应该调用 Init() 方法初始化 name和errorHandling
- 这样做的好处依然是更灵活地定制命令参数容器。但更重要的是,你的定制完全不会影响到那个全局变量flag.CommandLine
4.4.2. 解析参数:flag.Parse()
该方法应该在flag参数定义后, 具体参数值被访问之前调用。
4.4.2.1. 解析停止
第一个non-flag参数
当遇到单独的一个”-”或不是”-”开始时,会停止解析
两个连续的 ‘-’
5. 将 flag 绑定用户自定义类型
首先,用户自定义类型需要重新实现 flag.Value 接口
flag.Value 接口定义如下:
|
|
Note:
- String(): 方法输出结果为一个字符串值
- Set(string) error: 方法定义了如何解析flag参数指定的值
例如:解析数据库集群服务器的地址到一个 slice 中 ?
5.1. 重写 flag.Value
- 自定义flag参数值接收类型
|
|
- 实现 String() string 方法
|
|
- 实现 Set(string) error 方法
|
|
5.2. 解析
|
|
|
|
完整代码:
|
|
6. See Also
Thanks to the authors 🙂