zoukankan      html  css  js  c++  java
  • 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",22, "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, -1)
        }
        return flag.NormalizedName(name)
    }
    
    func main() {
        // 设置标准化参数名称的函数
        flag.CommandLine.SetNormalizeFunc(wordSepNormalizeFunc)
        
        // 为 age 参数设置 NoOptDefVal
        flag.Lookup("age").NoOptDefVal = "25"
    
        // 把 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",22, "Input Your Age")
    flag.Lookup("age").NoOptDefVal = "25"

    下面是传递参数的方式和参数最终的取值:

    Parsed Arguments     Resulting Value
    --age=30             cliAge=30
    --age                cliAge=25
    [nothing]            cliAge=22

    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=35

    注意 -- 后面的参数不会被解析:

    -oa=35 -- -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, -1)
        }
        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

  • 相关阅读:
    geoserver发布地图服务WMTS
    geoserver发布地图服务WMS
    geoserver安装部署步骤
    arcgis api 3.x for js 入门开发系列十四最近设施点路径分析(附源码下载)
    arcgis api 3.x for js 入门开发系列十三地图最短路径分析(附源码下载)
    cesium 之自定义气泡窗口 infoWindow 后续优化篇(附源码下载)
    arcgis api 3.x for js 入门开发系列十二地图打印GP服务(附源码下载)
    arcgis api 3.x for js 入门开发系列十一地图统计图(附源码下载)
    arcgis api 3.x for js 入门开发系列十叠加 SHP 图层(附源码下载)
    arcgis api 3.x for js入门开发系列九热力图效果(附源码下载)
  • 原文地址:https://www.cnblogs.com/sparkdev/p/10833186.html
Copyright © 2011-2022 走看看