笔者在前文中介绍了 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 包简介的更多相关文章

  1. Golang : cobra 包简介

    Cobra 是一个 Golang 包,它提供了简单的接口来创建命令行程序.同时,Cobra 也是一个应用程序,用来生成应用框架,从而开发以 Cobra 为基础的应用.本文的演示环境为 ubuntu 1 ...

  2. Golang : flag 包简介

    在 Golang 程序中有很多种方法来处理命令行参数.简单的情况下可以不使用任何库,直接处理 os.Args:其实 Golang 的标准库提供了 flag 包来处理命令行参数:还有第三方提供的处理命令 ...

  3. Golang : cobra 包解析

    笔者在<Golang : cobra 包简介>一文中简要的介绍了 cobra 包及其基本的用法,本文我们从代码的角度来了解下 cobra 的核心逻辑. Command 结构体 Comman ...

  4. GO语言的进阶之路-go的程序结构以及包简介

    GO语言的进阶之路-go的程序结构以及包简介 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.编辑,编译和运行 A,编辑 Go程序使用UTF-8编码的纯Unicode文本编写.大 ...

  5. Golang Vendor 包管理工具 glide 使用教程

    Glide 是 Golang 的 Vendor 包管理器,方便你管理 vendor 和 verdor 包.类似 Java 的 Maven,PHP 的 Composer. Github:https:// ...

  6. 【转】commons-lang.jar包简介

    转自:http://zhidao.baidu.com/share/71b48e6b3e1b1dc73fe705604b9c7584.html 1.下载jar包 包官方下载地址:http://commo ...

  7. Golang fmt包使用小技巧

    h1 { margin-top: 0.6cm; margin-bottom: 0.58cm; direction: ltr; color: #000000; line-height: 200%; te ...

  8. Hadoop2.0源码包简介

    Hadoop2.0源码包简介 1.解压源码包: 2.目录结构: hadoop-common-project:Hadoop基础库所在目录,如RPC.Metrics.Counter等.包含了其它所有模块可 ...

  9. Golang Vendor 包机制 及 注意事项

    现在的 Go 版本是 1.8,早在 1.5 时期,就有了 Vendor 包机制,详情可查看博文:“理解 Go 1.5 vendor”. 遇到的问题 个人在使用 Glide 管理 Vendor 包时(附 ...

随机推荐

  1. Struts2常见面试点

    01.  三层和MVC的区别 http://blog.csdn.net/csh624366188/article/details/7183872 http://www.cnblogs.com/zdxs ...

  2. 如何获取 Greenplum 中用户最后登录时间和登录频率

    这几天搞系统迁移,老板突然想知道给客户开的那么多用户当中,哪些还在用,哪些已经不用了.我们的数据库是 Greenplum,而且还是一直没有升级的老版本,Google 了一下没有发现特别好的查看用户登录 ...

  3. quick-cocos2d-x 系列之——环境搭建(Mac版)

    quick-cocos2d-x简单介绍 何为quick-cocos2d-x? ?   简单一句话:quick-cocos2d-x是採用lua语言,通过tolua++工具对cocos2d-x进一步封装, ...

  4. com.mysql.jdbc.exceptions.jdbc4.MySQLIntegrityConstraintViolationException: Duplicate entry '88888888' for key 'PRIMARY'

    严重: Servlet.service() for servlet jsp threw exceptioncom.mysql.jdbc.exceptions.jdbc4.MySQLIntegrityC ...

  5. javascript 跨浏览器事件处理

    <div id="myDiv" style="width:100px; height:100px; border:1px solid #f00;"> ...

  6. Could not find JSON in http://updates.jenkins-ci.org/update-center.json?id=default&version=2.7.4

    14-Sep-2016 21:43:58.241 INFO [Download metadata thread] hudson.model.AsyncPeriodicWork$1.run Finish ...

  7. BZOJ 3314 [Usaco2013 Nov]Crowded Cows:单调队列

    题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=3314 题意: N头牛在一个坐标轴上,每头牛有个高度.现给出一个距离值D. 如果某头牛在它的 ...

  8. blog集合

    godiscoder的技术blog 一个不错的技术架构设计blog MySQLOPS 数据库与运维自动化技术分享 stone的技术blog 陈皓专栏 风雪涟漪的技术blog 华为首席科学家 张宴技术b ...

  9. Mac环境下安装node.js、npm、express

    一:node.js安转 方法一:下载node.js for Mac 地址: http://nodejs.org/download/ 直接下载 pkg的,双击安装,一路点next,很容易就搞定了. 安装 ...

  10. 【Lintcode】062.Search in Rotated Sorted Array

    题目: Suppose a sorted array is rotated at some pivot unknown to you beforehand. (i.e., 0 1 2 4 5 6 7  ...