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


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM