Go解析命令行参数

在写命令行程序(工具、server)时,对命令行参数进行解析,是一种常见的需求。各种语言一般都会提供相应的方法或库,以方便开发者使用。在go标准库中提供了一个包:flag,方便进行命令行解析。也就是说,Go的flag包用来解析命令行参数。 

一、命令行flag语法形式

命令行flag的语法有如下三种形式:

-flag // 只支持bool类型
-flag=x
-flag x // 只支持非bool类型

其中,第一种形式只能用于bool类型。第三种形式只能用于非bool类型的flag。
第三种形式只能用于非bool类型的原因是:对于这样的命令 cmd -x *,如果有一个文件名字是:0或false等,则命令的原意会改变。因为bool类型支持-flag这种形式,所以go语言在Parse()方法中对bool类型进行了特殊处理。默认的,若提供了-flag,则对应的值为true;否则,则为flag.Bool/BoolVar中指定的默认值;如果希望显示地设置为false,则使用-flag=false。

二、定义flag的方式

定义flags有两种方式:

1)flag.Xxx(),其中Xxx可以是Int、String等;返回一个相应类型的指针,如:

var ip = flag.Int("flagname", 123, "int flag for flagname")

2)flag.XxxVar(),将flag绑定到一个变量上,如:

var flagvar int
flag.IntVar(&flagvar, "flagname", 123, "int flag for flagname")

另外,还可以创建自定义flag,只要实现flag.Value接口即可(要求receiver是指针),这时候可以通过如下方式定义该flag:

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

例如,解析以英文逗号分割的字符串直接到 slice 中,我们可以定义如下 Value:

type sliceValue []string

func newSliceValue(vals []string, p *[]string) *sliceValue {
    *p = vals
    return (*sliceValue)(p)
}

func (s *sliceValue) Set(val string) error {
    *s = sliceValue(strings.Split(val, ","))
    return nil
}

func (s *sliceValue) Get() interface{} { return []string(*s) }

func (s *sliceValue) String() string { return strings.Join([]string(*s), ",") }

之后,可以这么使用:

var languages []string
flag.Var(newSliceValue([]string{}, &languages), "slice", "I like programming `languages`")

这样通过 -slice “go,php” 这样的形式传递参数,languages 得到的就是 [go, php]。flag 包中对 Duration 这种非基本类型的支持,使用的就是类似这样的方式。

三、主要API

我们常用的API如下:

1. 直接获取命令行参数

// 获取名字为name的参数值,默认值为value,用法为usage
// 注意返回值是一个指针
// 类似的方法还有 Int(),Bool()等。
func String(name string, value string, usage string) *string

2. 将获取的命令行参数赋给指定值


// 这种方式p作为返回值,可以传入变量的地址
// 类似的方法还有 IntVar(),BoolVar()等。
func StringVar(p *string, name string, value string, usage string)

3. 展示使用方法

// Usage用来打印用法
var Usage = func() {
    // ...
}

4. 解析参数

// 解析参数,应在设置完参数变量后调用
func Parse()

四、使用示例

代码示例:

ackage main

import (
    "flag"
    "fmt"
//    "os"
)

func main() {
//    fmt.Println(os.Args)
    ok := flag.Bool("ok", false, "is ok")
    id := flag.Int("id", 0, "id")
    port := flag.String("port", ":8080", "http listen port")
    var name string
    flag.StringVar(&name, "name", "Jack", "name")

    flag.Parse()
//    flag.Usage()
    others := flag.Args()

    fmt.Println("ok:", *ok)
    fmt.Println("id:", *id)
    fmt.Println("port:", *port)
    fmt.Println("name:", name)
    fmt.Println("other:", others)
}

执行示例如下:

$ go run flag.go -ok -id 11111 -port 8899 -name TestUser very good
ok: true
id: 11111
port: 8899
name: TestUser
other: [very good]

猜你喜欢

转载自blog.csdn.net/chinawangfei/article/details/81979184