Golang : pflag 包简介
笔者在前文中介绍了 Golang 标准库中 flag 包的用法,事实上有一个第三方的命令行参数解析包 pflag 比 flag 包使用的更为广泛。pflag 包的设计目的就是替代标准库中的 flag 包,因此它具有更强大的功能并且与标准的兼容性更好。本文将介绍 pflag 包与 flag 包相比的主要优势,如果你还不了解 flag 包的的用法,请参考《Golang : flag 包简介》一文。本文的演示环境为 ubuntu 18.04。
pflag 包的主要特点
pflag 包与 flag 包的工作原理甚至是代码实现都是类似的,下面是 pflag 相对 flag 的一些优势:
- 支持更加精细的参数类型:例如,flag 只支持 uint 和 uint64,而 pflag 额外支持 uint8、uint16、int32 等类型。
- 支持更多参数类型:ip、ip mask、ip net、count、以及所有类型的 slice 类型。
- 兼容标准 flag 库的 Flag 和 FlagSet:pflag 更像是对 flag 的扩展。
- 原生支持更丰富的功能:支持 shorthand、deprecated、hidden 等高级功能。
安装 pflag 包
本文介绍 doker 源代码中引用的 pflag 包 github.com/spf13/pfla,用下面的命令安装该包:
$ go get github.com/spf13/pflag
入门 demo
在 Go workspace 的 src 目录下创建 pflagdemo 目录,并在目录下创建 main.go 文件,编辑其内容如下:
package main import flag "github.com/spf13/pflag"
import (
"fmt"
"strings"
) // 定义命令行参数对应的变量
var cliName = flag.StringP("name", "n", "nick", "Input Your Name")
var cliAge = flag.IntP("age", "a",, "Input Your Age")
var cliGender = flag.StringP("gender", "g","male", "Input Your Gender")
var cliOK = flag.BoolP("ok", "o", false, "Input Are You OK")
var cliDes = flag.StringP("des-detail", "d", "", "Input Description")
var cliOldFlag = flag.StringP("badflag", "b", "just for test", "Input badflag") func wordSepNormalizeFunc(f *flag.FlagSet, name string) flag.NormalizedName {
from := []string{"-", "_"}
to := "."
for _, sep := range from {
name = strings.Replace(name, sep, to, -)
}
return flag.NormalizedName(name)
} func main() {
// 设置标准化参数名称的函数
flag.CommandLine.SetNormalizeFunc(wordSepNormalizeFunc) // 为 age 参数设置 NoOptDefVal
flag.Lookup("age").NoOptDefVal = "" // 把 badflag 参数标记为即将废弃的,请用户使用 des-detail 参数
flag.CommandLine.MarkDeprecated("badflag", "please use --des-detail instead")
// 把 badflag 参数的 shorthand 标记为即将废弃的,请用户使用 des-detail 的 shorthand 参数
flag.CommandLine.MarkShorthandDeprecated("badflag", "please use -d instead") // 在帮助文档中隐藏参数 gender
flag.CommandLine.MarkHidden("badflag") // 把用户传递的命令行参数解析为对应变量的值
flag.Parse() fmt.Println("name=", *cliName)
fmt.Println("age=", *cliAge)
fmt.Println("gender=", *cliGender)
fmt.Println("ok=", *cliOK)
fmt.Println("des=", *cliDes)
}
代码本身很简单,也添加了注释,这里就不再过多的解释了。
运行 demo
在 flagdemo 目录下执行 go build 命令编译 demo 生成可执行文件 flagdemo。下面我们通过运行 demo 程序来了解 pflag 包命令行参数的语法特点。
布尔类型的参数
布尔类型的参数有下面几种写法
--flag // 等同于 --flag=true
--flag=value
--flag value // 这种写法只有在没有设置默认值时才生效

NoOptDefVal 用法
pflag 包支持通过简便的方式为参数设置默认值之外的值,实现方式为设置参数的 NoOptDefVal 属性:
var cliAge = flag.IntP("age", "a",, "Input Your Age")
flag.Lookup("age").NoOptDefVal = ""
下面是传递参数的方式和参数最终的取值:
Parsed Arguments Resulting Value
--age= cliAge=
--age cliAge=
[nothing] cliAge=

shorthand
与 flag 包不同,在 pflag 包中,选项名称前面的 -- 和 - 是不一样的。- 表示 shorthand,-- 表示完整的选项名称。
除了最后一个 shorthand,其它的 shorthand 都必须是布尔类型的参数或者是具有默认值的参数。
所以对于布尔类型的参数和设置了 NoOptDefVal 的参数可以写成下面的形式:
-o
-o=true
// 注意,下面的写法是不正确的
-o true
非布尔类型的参数和没有设置 NoOptDefVal 的参数的写法如下:
-g female
-g=female
-gfemale
日常的使用中一般会混合上面的两类规则:
-aon "jack"
-aon="jack"
-aon"jack"
-aonjack
-oa=
注意 -- 后面的参数不会被解析:
-oa= -- -gfemale

标准化参数的名称
如果我们创建了名称为 --des-detail 的参数,但是用户却在传参时写成了 --des_detail 或 --des.detail 会怎么样?默认情况下程序会报错退出,但是我们可以通过 pflag 提供的 SetNormalizeFunc 功能轻松的解决这个问题:
func wordSepNormalizeFunc(f *flag.FlagSet, name string) flag.NormalizedName {
from := []string{"-", "_"}
to := "."
for _, sep := range from {
name = strings.Replace(name, sep, to, -)
}
return flag.NormalizedName(name)
}
flag.CommandLine.SetNormalizeFunc(wordSepNormalizeFunc)
下面的写法也能正确设置参数了:
--des_detail="person detail"

把参数标记为即将废弃
在程序的不断升级中添加新的参数和废弃旧的参数都是常见的用例,pflag 包对废弃参数也提供了很好的支持。通过 MarkDeprecated 和 MarkShorthandDeprecated 方法可以分别把参数及其 shorthand 标记为废弃:
// 把 badflag 参数标记为即将废弃的,请用户使用 des-detail 参数
flag.CommandLine.MarkDeprecated("badflag", "please use --des-detail instead")
// 把 badflag 参数的 shorthand 标记为即将废弃的,请用户使用 des-detail 的 shorthand 参数
flag.CommandLine.MarkShorthandDeprecated("badflag", "please use -d instead")

在帮助文档中隐藏参数
pflag 包还支持在参数说明中隐藏参数的功能:
// 在帮助文档中隐藏参数 badflag
flag.CommandLine.MarkHidden("badflag")

看,帮助文档中没有显示 badflag 的信息。其实在把参数标记为废弃时,同时也会设置隐藏参数。
总结
正如本文中介绍的,pflag 包提供了很多非常棒的功能,这些功能方便了应用程序的开发者。因此越来越多的使用者抛弃标准库中的 flag 包转而使用 pflag 包解析命令行参数。
参考:
github spf13/pflag
Golang之使用Flag和Pflag
Golang命令行参数解析库源码分析:flag VS pflag
Golang : pflag 包简介的更多相关文章
- Golang : cobra 包简介
Cobra 是一个 Golang 包,它提供了简单的接口来创建命令行程序.同时,Cobra 也是一个应用程序,用来生成应用框架,从而开发以 Cobra 为基础的应用.本文的演示环境为 ubuntu 1 ...
- Golang : flag 包简介
在 Golang 程序中有很多种方法来处理命令行参数.简单的情况下可以不使用任何库,直接处理 os.Args:其实 Golang 的标准库提供了 flag 包来处理命令行参数:还有第三方提供的处理命令 ...
- Golang : cobra 包解析
笔者在<Golang : cobra 包简介>一文中简要的介绍了 cobra 包及其基本的用法,本文我们从代码的角度来了解下 cobra 的核心逻辑. Command 结构体 Comman ...
- GO语言的进阶之路-go的程序结构以及包简介
GO语言的进阶之路-go的程序结构以及包简介 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.编辑,编译和运行 A,编辑 Go程序使用UTF-8编码的纯Unicode文本编写.大 ...
- Golang Vendor 包管理工具 glide 使用教程
Glide 是 Golang 的 Vendor 包管理器,方便你管理 vendor 和 verdor 包.类似 Java 的 Maven,PHP 的 Composer. Github:https:// ...
- 【转】commons-lang.jar包简介
转自:http://zhidao.baidu.com/share/71b48e6b3e1b1dc73fe705604b9c7584.html 1.下载jar包 包官方下载地址:http://commo ...
- Golang fmt包使用小技巧
h1 { margin-top: 0.6cm; margin-bottom: 0.58cm; direction: ltr; color: #000000; line-height: 200%; te ...
- Hadoop2.0源码包简介
Hadoop2.0源码包简介 1.解压源码包: 2.目录结构: hadoop-common-project:Hadoop基础库所在目录,如RPC.Metrics.Counter等.包含了其它所有模块可 ...
- Golang Vendor 包机制 及 注意事项
现在的 Go 版本是 1.8,早在 1.5 时期,就有了 Vendor 包机制,详情可查看博文:“理解 Go 1.5 vendor”. 遇到的问题 个人在使用 Glide 管理 Vendor 包时(附 ...
随机推荐
- 流畅的python学习笔记:第十一章:抽象基类
__getitem__实现可迭代对象.要将一个对象变成一个可迭代的对象,通常都要实现__iter__.但是如果没有__iter__的话,实现了__getitem__也可以实现迭代.我们还是用第一章扑克 ...
- SAP-Function
[转]sap函数大全 ********SAP中常用函数 函数名 描述SD_VBAP_READ_WITH_VBELN 根据销售订单读取表vbap中的信息EDIT_LINES 把READ_TEXT返回的L ...
- HDU - 1495 非常可乐 【BFS】
题目链接 http://acm.hdu.edu.cn/showproblem.php?pid=1495 思路 首先 如果可乐的体积 是奇数 那么是无解的 然后 如果能够得到两杯 都是一般容量的可乐 那 ...
- 用vector代替实现二维数组
vector可以用来模拟数组,当然也可以用来模拟二维数组: 定义如:vector<int>a[100]; 相当于定义了一个100行的数组,当每行的大小是不确定的 模板应用如下: #in ...
- ansible mysql模块的使用今年
摘自: https://www.ibm.com/developerworks/cn/linux/1502_lih_ansible/
- 世界各国Google网址大全
http://www.oschina.net/question/100896_50293 冰岛 https://www.google.is/ 丹麦 https://www.google.dk/ 挪威 ...
- Linux- 恢复.swp文件
当我们对Linux文件系统下的文件编辑时,很多新手老手都有可能出现一些失误,在对一个文件编辑或者改动,甚至是不小心按到键盘并没有发现改动到某处时,没有强制退出(:q!)就直接退出,导致文件变成了.sw ...
- 关于JDK安装javac失效的几个问题。
1.按照指南一步一步配置环境变量. 打开cmd,测试. 2.如果还是没有用,注意你的JAVA_HOME配置的是用户变量还是系统变量,改成系统变量. 打开cmd,测试. 3.如果还是没有用,不要你的JA ...
- Jmeter-JDBC Request
1. 新建一个测试计划 2. 新建一个线程组 3. 创建数据库连接 4.配置数据库连接 5.添加JDBC Request 6.添加监听器
- leetcode 307. Range Sum Query - Mutable(树状数组)
Given an integer array nums, find the sum of the elements between indices i and j (i ≤ j), inclusive ...