Golang | flag & pflag介绍

flag

命令行语法

命令行语法主要有以下几种形式

-flag //只支持bool类型(加上该参数,解析值为true)
-flag=x
-flag x //只支持非bool类型

以上语法对于一个或两个‘-’号,效果是一样的。


常用函数

  • flag.String(), flag.Bool(), flag.Int(), flag.Float64() 返回对应类型的指针:func Xxx(name string, value Xxx, usage string) *Xxx
	arguments.IntPointer = flag.Int("int_pointer", 0, "help message for int_pointer")
	
	arguments.StringPointer = flag.String("string_pointer", "", "help message for string_pointer")
	
	arguments.FloatPointer = flag.Float64("float_pointer", 0.1, "help message for float_pointer")
	
	arguments.BoolPointer = flag.Bool("bool_pointer", false, "help message for bool_pointer")

  • flag.XxxVar() 将参数绑定到对应类型的指针:func XxxVar(p *Xxx, name string, value Xxx, usage string)
	flag.IntVar(&arguments.IntVariable, "int_variable", 0, "help message for int_variable")
	
	flag.StringVar(&arguments.StringVariable, "string_variable", "", "help message for string_variable")
	
	flag.Float64Var(&arguments.FloatVariable, "float_variable", 0.1, "help message for float_variable")
	
	flag.BoolVar(&arguments.BoolVariable, "bool_variable", false, "help message for bool_variable")
  • flag.Var() 绑定自定义类型:func Var(value Value, name string, usage string,自定义类型需要实现Value接口。Var定义了一个有指定名字和用法说明的标签。标签的类型和值是由第一个参数指定的,这个参数是Value类型,并且是用户自定义的实现了Value接口的类型。
	type Value interface {
		String() string
		Set(string) error
	}
  • flag.Parse() 解析命令行参数到定义的flag
    解析函数将会在碰到第一个非flag命令行参数时停止,非flag命令行参数是指不满足命令行语法的参数,如命令行参数为./selpg -s1 -e2 input.txt 则第一个非flag命令行参数为“input.txt”。
	flag.Parse()
  • flag.Args()flag.Arg(i)flag.NArg()
	// 在命令行标签被解析之后(遇到第一个非flag参数),flag.NArg()就返回解析后参数的个数。
	fmt.Println(flag.NArg())
	// flag.Args()返回非标签的命令行参数
	for i, arg := range flag.Args() {
		// flag.Arg(i)返回第i个命令行参数。
		fmt.Printf("%s %s\n", flag.Arg(i), arg)
	}
  • flag.Usage() 输出命令行的提示信息
	// 我们可以重定义Usage函数
	flag.Usage = func () {
		fmt.Println("**Some other message here**")
		flag.PrintDefaults()	// 默认提示信息
	}

例子

package main 

import (
	"flag"
	"fmt"
)

type Arguments struct{
	IntVariable 	int
	IntPointer 		*int
	StringVariable 	string 
	StringPointer 	*string 
	FloatVariable 	float64
	FloatPointer 	*float64
	BoolVariable	bool
	BoolPointer		*bool
}

var arguments Arguments

func init() {
	flag.IntVar(&arguments.IntVariable, "int_variable", 0, "help message for int_variable")
	arguments.IntPointer = flag.Int("int_pointer", 0, "help message for int_pointer")

	flag.StringVar(&arguments.StringVariable, "string_variable", "", "help message for string_variable")
	arguments.StringPointer = flag.String("string_pointer", "", "help message for string_pointer")
	
	flag.Float64Var(&arguments.FloatVariable, "float_variable", 0.1, "help message for float_variable")
	arguments.FloatPointer = flag.Float64("float_pointer", 0.1, "help message for float_pointer")
	
	flag.BoolVar(&arguments.BoolVariable, "bool_variable", false, "help message for bool_variable")
	arguments.BoolPointer = flag.Bool("bool_pointer", false, "help message for bool_pointer")
	flag.Usage = usage

	flag.Parse()
}

func usage() {
	fmt.Println("**Some other message here**")
	flag.PrintDefaults()
}

func main() {
	fmt.Printf("There are %d non-flags:\n", flag.NArg())
	for i, _ := range flag.Args() {
		fmt.Printf("%s\n", flag.Arg(i))
	}
	fmt.Println("*******************")
	fmt.Printf("IntVariable: %d\n", arguments.IntVariable)
	fmt.Printf("IntPointer: %d\n", *arguments.IntPointer)

	fmt.Printf("StringVariable: %s\n", arguments.StringVariable)
	fmt.Printf("StringPointer: %s\n", *arguments.StringPointer)

	fmt.Printf("FloatVariable: %f\n", arguments.FloatVariable)
	fmt.Printf("FloatPointer: %f\n", *arguments.FloatPointer)

	fmt.Printf("BoolVariable: %v\n", arguments.BoolVariable)
	fmt.Printf("BoolPointer: %v\n", *arguments.BoolPointer)
}
// 测试如下:
λ .\flag.exe -int_variable=1 -string_pointer "str" -float_pointer 1.0 non-flag -bool_variable
There are 2 non-flags:
non-flag
-bool_variable
*******************
IntVariable: 1
IntPointer: 0
StringVariable:
StringPointer: str
FloatVariable: 0.100000
FloatPointer: 1.000000
BoolVariable: false
BoolPointer: false

λ .\flag.exe -int_variable=1 -string_pointer"str" -float_pointer 1.0 -bool_variable
flag provided but not defined: -string_pointerstr
**Some other message here**
  -bool_pointer
        help message for bool_pointer
  -bool_variable
        help message for bool_variable
  -float_pointer float
        help message for float_pointer (default 0.1)
  -float_variable float
        help message for float_variable (default 0.1)
  -int_pointer int
        help message for int_pointer
  -int_variable int
        help message for int_variable
  -string_pointer string
        help message for string_pointer
  -string_variable string
        help message for string_variable

自定义参数类型:

package main 

import (
	"errors"
	"fmt"
	"flag"
	"strings"
	"strconv"
)

type MySlice []int

/**
 * 实现Value接口
 *	- String() string
 *	- Set(string) error
 */
func (mySlice *MySlice) String() string {
	return fmt.Sprintf("%v", *mySlice)
}

func (mySlice *MySlice) Set(value string) error {
	if len(*mySlice) > 0 {
		return errors.New("MySlice has already been set!")
	}
	for _, numStr := range strings.Split(value, ",") {
		num, err := strconv.Atoi(numStr)
		if err == nil {
			*mySlice = append(*mySlice, num)
		} else {
			return errors.New("Your input has some non-integers")
		}
	}
	return nil
}

var mySlice MySlice

func init() {
	flag.Var(&mySlice, "slice", "a slice of some integers")
	flag.Parse()
}

func main() {
	fmt.Println(mySlice)
}
// 测试如下:
λ .\flag.Var.exe -slice 2,3,1
[2 3 1]

pflag

pflag是Go flag包的一个替代插件,实现了POSIX / GNU风格的flag,基本使用于"flag"包基本相同。
安装

go get github.com/spf13/pflag

参数解析

  • 默认参数以--作为前缀:
--flag 	 # 只支持bool类型
--flag=x 
--flag x # 只支持非bool类型

pflag包还定义了一些不在flag中的新函数,这些函数为flag提供了一个字母的缩写。可以通过将“P”附加到定义标志的任何函数的名称上来使用它们。

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")

此时,参数也可以以-为前缀:

-flag 	 # 只支持bool类型
-flag=x 
-flag x # 只支持非bool类型
-flagx	# 只支持非bool类型

结束符--后标志解析停止。与flag包不同,flag可以在这个结束符之前的命令行中的任何地方散布参数。
Integer标志接受1234、0664、0x 1234,并且可以是负数。Boolen标志接受1,0,t, f, true, false, TRUE, FALSE, True, False。Duration标志接受任何符合time.ParseDuration的输入。
设置非必须选项的默认值

var ip = flag.IntP("flagname", "f", 1234, "help message")
flag.Lookup("flagname").NoOptDefVal = "4321"
Parsed Arguments Resulting Value
–flagname=1357 ip=1357
–flagname ip=4321
[nothing] ip=1234

其他新增方法详见源码。

猜你喜欢

转载自blog.csdn.net/liuyh73/article/details/83025435