Golang flag包——处理命令行参数

1、概述 

在golang中有很多方法来处理命令行参数,简单情况下可以不使用任何库,直接使用os.Args;但是golang标准库提供了flag包来处理命令行参数;还有第三方提供的处理命令行参数的库cobra、cli等。

2、os.Args

如果你只是简单的想要获取命令行参数,可以像下面的代码示例一样使用os.Args来获取命令行参数。

package main

import (
    "fmt"
    "os"
)

//os.Args demo
func main() {
    //os.Args是一个[]string
    if len(os.Args) > 0 {
        for index, arg := range os.Args {
            fmt.Printf("args[%d]=%v\n", index, arg)
        }
    }
}

将上面的代码执行go build -o "args_demo"编译之后,执行:

$ ./args_demo a b c d
args[0]=./args_demo
args[1]=a
args[2]=b
args[3]=c
args[4]=d

os.Args是一个存储命令行参数的字符串切片,它的第一个元素是执行文件的名称。

2、flag包基本使用

2.1 flag包绑定解析参数有三种定义方式

1、flag.Type()

基本格式如下:

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

例如:flag.Int, flag.String, 返回解析变量类型的指针

package main

import (
    "flag"
    "fmt"
)

func main() {
    host := flag.String("host", "10.20.30.29", "请输入host地址")
    port := flag.Int("port", 8080, "请输入端口号")
    flag.Parse() // 解析参数
    fmt.Printf("%s:%d\n", *host, *port)
}

执行: go run main.go -host=10.20.30.31 -port=8080
输出:10.20.30.31:8080
当然你也可以直接执行go run main.go, 这时候就会使用你的默认值,10.20.31.29:8080。

2、flag.TypeVar()

基本格式如下: 

flag.TypeVar(Type指针, flag名, 默认值, 帮助信息)

例如:flag.IntVar, flag.StringVar

package main

import (
    "flag"
    "fmt"
)
var host string
var port int

func init() { // 每个文件会自动执行的函数
    flag.StringVar(&host, "host", "10.20.30.29", "请输入host地址")
    flag.IntVar(&port, "port", 8080, "请输入端口号")
}

func main() {
    flag.Parse() // 解析参数
    fmt.Printf("%s:%d\n", host, port)
}

执行结果同上。

3、自定义参数解析flag.Var()

我们可以看下flag.go源码:

func Var(value Value, name string, usage string) {
    CommandLine.Var(value, name, usage)
}

type Value interface {
    String() string
    Set(string) error
}

使用flag.Var函数第一个参数我们需要传入一个Value类型的值,Value是一个接口类型,定义了两个方法,接下来我们去实现这两个方法:

package main

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

// 自定义类型
type HandsomeBoys []string

// 实现String()方法
func (h *HandsomeBoys) String() string {
    return fmt.Sprintf("%v", *h)
}

// 实现Set方法,Set接口决定了如何解析flag的值
func (h *HandsomeBoys) Set(s string) error {
    for _, v := range strings.Split(s, ",") {
        *h = append(*h, v)
    }
    return nil
}

// 定义一个HandsomeBoys类型的变量
var boys HandsomeBoys

func init() {
    // 绑定变量boys
    flag.Var(&boys, "boys", "请输入一组帅气的男孩名称:-boys=张三,李四")
}

func main() {
    flag.Parse()
    fmt.Println(boys)
}

运行代码: go run main.go -boys=张三,李四

[张三,李四]

2.2 flag.Parse() 

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

注意:flag 中 类似 String() 或者 StringVar() 这样的方法仅仅是把参数名以及接收值的内存地址还有默认值等等参数关联起来而已,他并没有真正的开始从 arguments 中解析注册到 flag。因此必须要在你定义接收好 flag 参数之前并且在访问这些参数之前调用 flag.Parse()。

3、结合Goland使用flag包示例

示例:

func main() {
	var metricsAddr string
	var enableLeaderElection bool
	var probeAddr string
	var watchNamespaces string
	var logPath string
	flag.StringVar(&watchNamespaces, "watch-namespaces", "", "Optional comma separated list of namespaces to watch for resources in. Defaults to cluster scope.")
	flag.StringVar(&metricsAddr, "metrics-bind-address", ":8080", "The address the metric endpoint binds to.")
	flag.StringVar(&probeAddr, "health-probe-bind-address", ":8081", "The address the probe endpoint binds to.")
	flag.BoolVar(&enableLeaderElection, "leader-elect", false,
		"Enable leader election for controller manager. "+
			"Enabling this will ensure there is only one active controller manager.")
	opts := zap.Options{
		Development: true,
	}
	opts.BindFlags(flag.CommandLine)
	flag.Parse()
.....
}

通过Goland传参给Go文件,注意必须要在你定义接收好 flag 参数之前并且在访问这些参数之前调用 flag.Parse()。

参考:https://www.cnblogs.com/aaronthon/p/10883711.html

参考:https://blog.csdn.net/weixin_42278305/article/details/110133125

参考:https://blog.csdn.net/qq_17303159/article/details/112058496

posted @ 2022-01-16 23:10  人艰不拆_zmc  阅读(1194)  评论(0编辑  收藏  举报