Golang Flags包的使用
简介
需要从外部传入一些依赖参数的的时候,一般来说有如下的两种方案:
- 配置文件
- 利用flags包,从命令行传入
配置文件的方法我之前介绍过解决方案,有兴趣的可以去这里看看
demo
话不多说,直接上例子
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24package main
import (
"flag"
"fmt"
)
var (
arg1 string
arg2 int
arg3 bool
)
func init() {
flag.StringVar(&arg1, "arg1", "defaultArg1", "arg1")
flag.IntVar(&arg2, "arg2", 12, "arg2")
flag.BoolVar(&arg3, "arg3", false, "arg3")
flag.Parse()
}
func main() {
fmt.Println("arg1 = ", arg1)
fmt.Println("arg2 = ", arg2)
fmt.Println("arg3 = ", arg3)
}运行
1
2
3
4
5
6
7
8
9> go run aaa.go -h
Usage of /var/folders/sx/zv6vr6pd4gsc1vv2fmbq5dyw0000gn/T/go-build386487880/b001/exe/aaa:
-arg1 string
arg1 (default "defaultArg1")
-arg2 int
arg2 (default 12)
-arg3
arg3
exit status 2
1 | # 默认值 |
flag包参数传入
- 定义命令行参数有3种方式
flag.Xxx()
其中 Xxx 可以是 Int、String,Bool 等;返回一个相应类型的指针。
1
2
3
4
5// Int defines an int flag with specified name, default value, and usage string.
// The return value is the address of an int variable that stores the value of the flag.
func Int(name string, value int, usage string) *int {
return CommandLine.Int(name, value, usage)
}demo
1
var ip = flag.Int("flagname", 1234, "help message for flagname")
第一个参数 :flag名称为flagname
第二个参数 :flagname默认值为1234
第三个参数 :flagname的提示信息
flag.XxxVar()
将 flag 绑定到一个变量上
1
2
3
4
5// IntVar defines an int flag with specified name, default value, and usage string.
// The argument p points to an int variable in which to store the value of the flag.
func (f *FlagSet) IntVar(p *int, name string, value int, usage string) {
f.Var(newIntValue(value, p), name, usage)
}demo
1
2var flagValue int
flag.IntVar(&flagValue, "flagname", 1234, "help message for flagname")第一个参数 :接收flagname的实际值的
第二个参数 :flag名称为flagname
第三个参数 :flagname默认值为1234
第四个参数 :flagname的提示信息
flag.Var()
- 用于自定义类型,首先来个demo
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42package main
import (
"flag"
"fmt"
"strings"
)
type mySlice []string
/* Value接口:
type Value interface {
String() string
Set(string) error
}
实现flag包中的Value接口,将命令行接收到的值用,分隔存到slice里
*/
//new一个存放命令行参数值的slice
func newMySlice(val []string, p *[]string) *mySlice {
*p = val
return (*mySlice)(p)
}
func (s *mySlice) Set(val string) error {
*s = mySlice(strings.Split(val, ","))
return nil
}
func (s *mySlice) String() string {
*s = mySlice(strings.Split("default value", ","))
return ""
}
func main() {
var mySlices []string
flag.Var(newMySlice([]string{}, &mySlices), "my-slice", "my slices")
flag.Parse()
//打印结果slice接收到的值
fmt.Println(mySlices)
} - 这样通过 -my-slice “go,php” mySlices 得到的就是 [go, php]。如果不加-my-slice参数则打印默认值[default value]
- flag.Var()函数的第一个入参是一个接口
1
2
3
4
5
6
7
8
9
10
11
12
13
14// Value is the interface to the dynamic value stored in a flag.
// (The default value is represented as a string.)
//
// If a Value has an IsBoolFlag() bool method returning true,
// the command-line parser makes -name equivalent to -name=true
// rather than using the next command-line argument.
//
// Set is called once, in command line order, for each flag present.
// The flag package may call the String method with a zero-valued receiver,
// such as a nil pointer.
type Value interface {
String() string
Set(string) error
} - 看注释可以看出来,如果没有传入,则调用String()函数;如果有传入,则调用Set()函数
flag包的Set
- 适用于n功能合1,但是只有单入口的main.go
- 首先看flag包中的函数
1
2
3
4
5
6
7
8
9
10
11// NewFlagSet returns a new, empty flag set with the specified name and
// error handling property. If the name is not empty, it will be printed
// in the default usage message and in error messages.
func NewFlagSet(name string, errorHandling ErrorHandling) *FlagSet {
f := &FlagSet{
name: name,
errorHandling: errorHandling,
}
f.Usage = f.defaultUsage
return f
}demo
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60package main
import (
"flag"
"fmt"
"os"
)
func main() {
var (
serverFlag struct {
mysqlAddr string
port int
}
clientFlag struct {
serverAddr string
port int
}
)
flag.Usage = func() {
fmt.Fprintf(os.Stderr, "Usage: %s {client|server} \n", os.Args[0])
flag.PrintDefaults()
}
// set client flags
clientSet := flag.NewFlagSet("client", flag.ExitOnError)
clientSet.StringVar(&clientFlag.serverAddr, "server", "127.0.0.1", "server address")
clientSet.IntVar(&clientFlag.port, "port", 1080, "server port")
// set server flags
serverSet := flag.NewFlagSet("server", flag.ExitOnError)
serverSet.StringVar(&serverFlag.mysqlAddr, "mysql", "127.0.0.1:6379", "mysql address")
serverSet.IntVar(&serverFlag.port, "port", 1080, "server port")
if len(os.Args) < 2 {
flag.Usage()
os.Exit(1)
}
switch os.Args[1] {
case "client":
clientSet.Parse(os.Args[2:])
case "server":
serverSet.Parse(os.Args[2:])
default:
flag.Usage()
os.Exit(1)
}
if serverSet.Parsed() {
fmt.Println("server ")
fmt.Println(serverFlag)
}
if clientSet.Parsed() {
fmt.Println("client")
fmt.Println(clientFlag)
}
} - 这样就实现了二合一