golang 基础库之go获取命令行参数,介绍了如何使用flag包创建程序交互操作
使用flag包创建程序交互操作
Golang 版本
1.12.1
前言
通过flag定义程序交互接口的方法主导了基于GNU/Linux
、BSD
和macOS
的系统。比如ls -l
在*NIX
系统上列出当前目录中的文件就是一个典型的例子。
Go版本的flag包不支持flag的组合,例如ls -ll
,所以每个flag必须分开。还有就是Go flag包也不区分长短选项。最后,-flag
和--flag
是等价的。
实现
package main
import (
"flag"
"fmt"
"log"
"os"
"strings"
)
// 自定义类型需要实现flag.Value
// 接口才能在flag.Var函数中使用它
type ArrayValue []string
func (s *ArrayValue) String() string {
return fmt.Sprintf("%v", *s)
}
func (a *ArrayValue) Set(s string) error {
*a = strings.Split(s, ",")
return nil
}
func main() {
// 使用返回指针的方法提取flag值
retry := flag.Int("retry", -1, "定义最大重试次数")
// 使用XXXVar方法读取flag值
// 在这种情况下,必须在标志之前定义变量
var logPrefix string
flag.StringVar(&logPrefix, "prefix", "", "Logger 前缀")
var arr ArrayValue
flag.Var(&arr, "array", "输入数组迭代")
// 执行flag.Parse函数,
// 读取已定义变量的flag。
// 没有这个调用,flag变量保持为空。
flag.Parse()
// 与flag功能无关,只是例子逻辑的一部分
logger := log.New(os.Stdout, logPrefix, log.LstdFlags)
retryCount := 0
for retryCount < *retry {
logger.Println("连接重试...")
logger.Printf("发送的数组 %v\n", arr)
retryCount++
}
}
通过 go build -o util
编译为二进制文件
在命令行中执行 ./util -retry 2 -prefix=test -array=1,2,3
返回如下结果
$ ./util -retry 2 -prefix test -array=1,2,3
test2019/05/14 08:52:45 连接重试...
test2019/05/14 08:52:45 发送的数组 [1 2 3]
test2019/05/14 08:52:45 连接重试...
test2019/05/14 08:52:45 发送的数组 [1 2 3]
原理
对于在程序中获取flag值,flag包定义了两种类型的函数。
第一种类型是简单名称,比如Int
。此函数将返回指向已解析flag值的整数变量的指针。
第二种是xxxVar
这种类型的方法。它们提供相同的功能,但你需要提供指向变量的指针,以便于将解析的flag值存储在给定的变量中。
Go 库还支持自定义flag类型,函数是Var
。自定义类型必须实现flag包中value
的接口。上述代码中ArrayValue
变量就是实现了flag包中value
的String
和Set
接口。
上面代码最重要部分是parse()
解析flag的函数。在定义所有flag之后并且在访问值之前,必须进行调用,否则将获取不到传入的值。
延伸
flag包中还包含flag处理的底层函数,以满足不同的需求,推荐阅读一下FlagSet
的文档。