Golang | Stdlib: Flag 学习笔记
source link: https://ijayer.github.io/post/tech/code/golang/20180912-stdlib-flag/
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
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 🙂
Recommend
About Joyk
Aggregate valuable and interesting links.
Joyk means Joy of geeK