科科人神
9 min

pflag 中文文档

pflag 中文文档,本文档基于 pflag 官方文档。不定期更新。

Build StatusGo Report CardGoDoc

Description

pflag 是 Go flag 包的一个替代品,实现了 POSIX/GNU-style --flags

pflag 兼容 GNU extensions to the POSIX recommendations for command-line options. 有关更精确的说明,请参阅下面的 “Command-line flag syntax” 部分。

pflag 在与 Go 语言相同的 BSD 许可证样式下可用,可以在 LICENSE 文件中找到。

Installation

pflag 可以通过标准的 go get 命令使用。

安装:

go get github.com/spf13/pflag

测试:

go test github.com/spf13/pflag

Usage

pflag 是 Go 原生 flag 包的一个替代品。如果你以 flag 的名称导入 pflag,那么所有代码都应该继续运行,不需要任何更改。

import flag "github.com/spf13/pflag"

这有一个例外:如果直接实例化 Flag struct,则还需要设置一个 Shorthand 字段。 大多数代码从不直接实例化此结构,而是使用 String()BoolVar()Var() 等函数,因此不受影响。

使用 flag.String()Bool()Int() 等定义标志。

这里声明了一个整数标志 -flagname,存储在指针 ip 中,类型为 *int

var ip *int = flag.Int("flagname", 1234, "help message for flagname")

如果愿意,可以使用 Var() 函数将标志绑定到变量。

var flagvar int
func init() {
    flag.IntVar(&flagvar, "flagname", 1234, "help message for flagname")
}

或者,你可以创建满足 Value 接口(使用指针接收器)的自定义标志,将它们结合起来标记解析

flag.Var(&flagVal, "name", "help message for flagname")

对于此类标志,默认值是变量的初始值。

定义完所有标志后,调用

flag.Parse()

将命令行解析为定义的标志。

然后可以直接使用标志。如果你直接使用 flag 本身,它们都是指针; 如果你绑定到变量,它们就是值。

fmt.Println("ip has value ", *ip)
fmt.Println("flagvar has value ", flagvar)

如果你有一个 FlagSet,但是发现很难跟踪代码中的所有指针,可以使用一些辅助函数来获取存储在标志中的值。 如果你有一个 pflag.FlagSet,带有一个名为 flagnameint 类型的标志,你可以使用 GetInt() 来获取 int 值。 但请注意 flagname 必须存在且必须是 intGetString("flagname") 会失败。

i, err := flagset.GetInt("flagname")

解析后,标志后面的参数 flag.Args() 可作为 slice 使用,flag.Arg(i)可单独使用。 参数下标 0flag.NArg() - 1

pflag 包还定义了一些不在 flag 中的新函数,这些函数为 flag 提供了一个字母缩写。你可以通过将P附加到定义标志的任意函数名来调用这些函数, 比如 intVar() 加上 P 就是 intVarP()

var ip = flag.IntP("flagname", "f", 1234, "help message")
var flagvar bool
func init() {
	flag.BoolVarP(&flagvar, "boolname", "b", true, "help message")
}
flag.VarP(&flagVal, "varname", "v", "help message")

简写字母可以在命令行上使用单个 -。 布尔简写标志可以与其他简写标志组合使用。

默认的命令行标志集由顶级函数控制。FlagSet 类型允许定义独立的标志集,例如在命令行接口中实现子命令。 FlagSet 的方法类似于命令行标志集的顶级函数。

不为标志设置选项默认值

创建一个 flag 后,可以为这个 flag 设置 pflag.NoOptDefVal。这样做会稍微改变标志的含义。 如果一个 flag 具有 NoOptDefVal,并且该 flag 在命令行上没有设置这个 flag 的值,则该标志将设置为 NoOptDefVal 指定的值。举个例子:

var ip = flag.IntP("flagname", "f", 1234, "help message")
flag.Lookup("flagname").NoOptDefVal = "4321"

会产生下面类似的结果

Parsed ArgumentsResulting Value
--flagname=1357ip=1357
--flagnameip=4321
[nothing]ip=1234

Command line flag syntax

--flag    // boolean flags, or flags with no option default values
--flag x  // only on flags without a default value
--flag=x

与 flag 包不同,选项前的一个 - 与两个 -- 的意思是不同的。一个 - 表示 flag 的简写字母。 除了最后一个简写字母之外,其他所有字母都必须是布尔标志或具有默认值的标志。

// boolean or flags where the 'no option default value' is set
-f
-f=true
-abc
but
-b true is INVALID

// non-boolean and flags without a 'no option default value'
-n 1234
-n=1234
-n1234

// mixed
-abcs "hello"
-absd="hello"
-abcs1234

结束符 -- 之后停止标志解析。与 flag 包不同,标志可以在此终结符之前在命令行的任何位置穿插参数。

整数标志接受 1234,0664,0x1234 并且可能是负数。 布尔标志(长格式)接受 10tftruefalseTRUEFALSETrueFalse。 Duration 标志接受对 time.ParseDuration 有效的任何输入。

Mutating or "Normalizing" Flag names

可以设置一个自定义标志名的 “normalization function”。它允许在代码中创建时以及在命令行上使用某些需要 “normalized” 的形式时,标记名都会发生 normalized。 “normalized” 形式一般用于比较。下面是使用自定义 “normalized” 函数的两个示例。

例 #1: 你想要 -_. 在标志中进行比较是是一样的。比如 --my-flag == --my_flag == --my.flag

func wordSepNormalizeFunc(f *pflag.FlagSet, name string) pflag.NormalizedName {
	from := []string{"-", "_"}
	to := "."
	for _, sep := range from {
		name = strings.Replace(name, sep, to, -1)
	}
	return pflag.NormalizedName(name)
}

myFlagSet.SetNormalizeFunc(wordSepNormalizeFunc)

例 #2: 你想要给两个标志设置别名。例如--old-flag-name == --new-flag-name

func aliasNormalizeFunc(f *pflag.FlagSet, name string) pflag.NormalizedName {
	switch name {
	case "old-flag-name":
		name = "new-flag-name"
		break
	}
	return pflag.NormalizedName(name)
}

myFlagSet.SetNormalizeFunc(aliasNormalizeFunc)

Deprecating a flag or its shorthand

可以弃用标志或者标志的简写。弃用的 标志/简写 在帮助文本中会被隐藏,并在使用不推荐的 标志/简写 时打印正确的用法提示。

例 #1: 你想要弃用名为 “badflag” 的标志,并告知用户应该使用哪个标志代替。

// deprecate a flag by specifying its name and a usage message
flags.MarkDeprecated("badflag", "please use --good-flag instead")

这样隐藏了帮助文本中的 badflag,并且当使用 badflag 时打印了 Flag --badflag has been deprecated, please use --good-flag instead

例 #2: 你希望保留名为 noshorthandflag 的标志,但是弃用它的简写 n

// deprecate a flag shorthand by specifying its flag name and a usage message
flags.MarkShorthandDeprecated("noshorthandflag", "please use --noshorthandflag only")

这样隐藏了帮助文本中的简写 n,并且当使用简写 n 时打印了 Flag shorthand -n has been deprecated, please use --noshorthandflag only

注意,usage message 在此处必不可少,并且不应为空

Hidden flags

可以将 flag 标记为隐藏的,这意味着它仍将正常运行,但不会显示在 usage/help 文本中。

: 你有一个名为 secretFlag 的标志,你只需要内部使用,并且不希望它显示在帮助文本中,或者它的使用文本显示。

// hide a flag by specifying its name
flags.MarkHidden("secretFlag")

Disable sorting of flags

pflag允许你禁用 flag 的 help 和 usage 的排序。

:

flags.BoolP("verbose", "v", false, "verbose output")
flags.String("coolflag", "yeaah", "it's really cool flag")
flags.Int("usefulflag", 777, "sometimes it's very useful")
flags.SortFlags = false
flags.PrintDefaults()

Output:

  -v, --verbose           verbose output
      --coolflag string   it's really cool flag (default "yeaah")
      --usefulflag int    sometimes it's very useful (default 777)

Supporting Go flags when using pflag

为了支持使用 Go 的 flag 包定义的 flag ,必须将它们添加到 pflag 标志集中。这通常是支持第三方依赖项定义的标志所必需的(例如 golang/glog)。

: 你想要将 Go flags 添加到 CommandLine 标志集

import (
	goflag "flag"
	flag "github.com/spf13/pflag"
)

var ip *int = flag.Int("flagname", 1234, "help message for flagname")

func main() {
	flag.CommandLine.AddGoFlagSet(goflag.CommandLine)
	flag.Parse()
}

More info

你可以在 godoc.org 查看 pflag 包的完整参考文档,或在安装后通过 go 的标准文档系统运行 godoc -http =:6060 并浏览器打开 http//localhost6060/pkg/github.com/spf13/pflag

Last Updated: