ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

Go语言flag包:命令行解析

2021-11-14 14:32:52  阅读:133  来源: 互联网

标签:slice string flag 参数 命令行 Go name


转载:http://c.biancheng.net/view/5573.html
在编写命令行程序(工具、server)时,需要对命令行参数进行解析,各种编程语言一般都会提供解析命令行参数的方法或库,以便程序员使用。
Go语言中的flag包中,提供了命令行参数解析的功能。

概念:

  • 命令行参数(或参数):是指运行程序时提供的参数;
  • 已定义命令行参数:是指程序中通过 flag.Type 这种形式定义了的参数;
  • 非 flag(non-flag)命令行参数(或保留的命令行参数):可以简单理解为 flag 包不能解析的参数。

flag参数类型

flag包支持的命令行参数类型有bool、int、int64、uint、uint64、float、float64、string、duration,如下表所示:

flag包基本使用

有以下两种常用的定义命令行 flag 参数的方法:

1) flag.Type()

基本格式如下:

flag.Type(flag 名, 默认值, 帮助信息) *Type

Type 可以是 Int、String、Bool 等,返回值为一个相应类型的指针,例如我们要定义姓名、年龄、婚否三个命令行参数,我们可以按如下方式定义:

name := flag.String("name", "张三", "姓名")
age := flag.Int("age", 18, "年龄")
married := flag.Bool("married", false, "婚否")
delay := flag.Duration("d", 0, "时间间隔")

需要注意的是,此时 name、age、married、delay 均为对应类型的指针

2) flag.TypeVar()

基本格式如下:
flag.TypeVar(Type 指针, flag 名, 默认值, 帮助信息)

TypeVar 可以是 IntVar、StringVar、BoolVar 等,其功能为将 flag 绑定到一个变量上,例如我们要定义姓名、年龄、婚否三个命令行参数,我们可以按如下方式定义:

var name string
var age int
var married bool
var delay time.Duration
flag.StringVar(&name, "name", "张三", "姓名")
flag.IntVar(&age, "age", 18, "年龄")
flag.BoolVar(&married, "married", false, "婚否")
flag.DurationVar(&delay, "d", 0, "时间间隔")

flag.Parse()
通过以上两种方法定义好命令行 flag 参数后,需要通过调用 flag.Parse() 来对命令行参数进行解析。

支持的命令行参数格式有以下几种:

  • -flag:只支持 bool 类型;
  • -flag=x;
  • -flag x:只支持非 bool 类型。

其中,布尔类型的参数必须使用等号的方式指定。
flag 包的其他函数:

  • flag.Args() //返回命令行参数后的其他参数,以 []string 类型
  • flag.NArg() //返回命令行参数后的其他参数个数
  • flag.NFlag() //返回使用的命令行参 数个数

示例:

package main

import (
    "flag"
    "fmt"
)

var Input_pstrName = flag.String("name", "gerry", "input ur name")
var Input_piAge = flag.Int("age", 20, "input ur age")
var Input_flagvar int

func Init() {
    flag.IntVar(&Input_flagvar, "flagname", 1234, "help message for flagname")
}

func main() {
    Init()
    flag.Parse()

    // After parsing, the arguments after the flag are available as the slice flag.Args() or individually as flag.Arg(i). The arguments are indexed from 0 through flag.NArg()-1
    // Args returns the non-flag command-line arguments
    // NArg is the number of arguments remaining after flags have been processed
    fmt.Printf("args=%s, num=%d\n", flag.Args(), flag.NArg())
    for i := 0; i != flag.NArg(); i++ {
        fmt.Printf("arg[%d]=%s\n", i, flag.Arg(i))
    }

    fmt.Println("name=", *Input_pstrName)
    fmt.Println("age=", *Input_piAge)
    fmt.Println("flagname=", Input_flagvar)
}

运行结果:

go run main.go -name "aaa" -age=123 -flagname=999
args=[], num=0
name= aaa
age= 123
flagname= 999

自定义 Value

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

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

【示例】解析喜欢的编程语言,并直接解析到 slice 中,我们可以定义如下 sliceValue 类型,然后实现 Value 接口:

package main

import (
    "flag"
    "fmt"
    "strings"
)

//定义一个类型,用于增加该类型方法
type sliceValue []string

//new一个存放命令行参数值的slice
func newSliceValue(vals []string, p *[]string) *sliceValue {
    *p = vals
    return (*sliceValue)(p)
}

/*
Value接口:
type Value interface {
    String() string
    Set(string) error
}
实现flag包中的Value接口,将命令行接收到的值用,分隔存到slice里
*/
func (s *sliceValue) Set(val string) error {
    *s = sliceValue(strings.Split(val, ","))
    return nil
}

//flag为slice的默认值default is me,和return返回值没有关系
func (s *sliceValue) String() string {
    *s = sliceValue(strings.Split("default is me", ","))
    return "It's none of my business"
}

/*
可执行文件名 -slice="java,go"  最后将输出[java,go]
可执行文件名 最后将输出[default is me]
*/
func main(){
    var languages []string
    flag.Var(newSliceValue([]string{}, &languages), "slice", "I like programming `languages`")
    flag.Parse()

    //打印结果slice接收到的值
    fmt.Println(languages)
}

通过-slice go,php 这样的形式传递参数,languages 得到的就是 [go, php],如果不加-slice 参数则打印默认值[default is me],如下所示:

go run main.go -slice go,php,java
[go php java]

flag 中对 Duration 这种非基本类型的支持,使用的就是类似这样的方式,即同样实现了 Value 接口。

标签:slice,string,flag,参数,命令行,Go,name
来源: https://www.cnblogs.com/whiteBear/p/15551724.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有