1. 程式人生 > >Go語言-命令列引數(os.Args, flag包)

Go語言-命令列引數(os.Args, flag包)

大部分Go程式都是沒有UI的,執行在純命令列的模式下,該幹什麼全靠執行引數。
這裡介紹下Go語言命令列程式和他們的引數。

1. os.Args

程式獲取執行他時給出的引數,可以通過os包來實現。先看程式碼:

package main

import (
    "fmt"
    "os"
    "strconv"
)

func main () {
    for idx, args := range os.Args {
        fmt.Println("引數" + strconv.Itoa(idx) + ":", args)
    }
}

執行起來得到的如下:

$go
run main.go 1 3 -X ? 引數0: /tmp/go-build116558042/command-line-arguments/_obj/exe/main 引數1: 1 引數2: 3 引數3: -X 引數4: ?

可以看到,命令列引數包括了程式路徑本身,以及通常意義上的引數。
程式中os.Args的型別是 []string ,也就是字串切片。所以可以在for迴圈的range中遍歷,還可以用 len(os.Args) 來獲取其數量。

如果不想要輸出os.Args的第一個值,也就是可執行檔案本身的資訊,可以修改上述程式:

for idx, args := range os
.Args[1:] {

將range後面的切片,去掉第一個元素。
輸出切片的所有元素,還有更簡潔的方式:

fmt.Println(strings.Join(os.Args[1:], "\n"))
fmt.Println(os.Args[1:])
/*
後一種方式的結果是[1 3 -X ?],這是fmt.Println輸出切片的格式
*/

2. flag包

flag包相比單純的通過os.Args切片分析命令列引數,提供了更強的能力,同時也是風複雜的用法。
來看個例子:

package main
import (
    "fmt"
    "flag"
)
var
b = flag.Bool("b", false, "bool型別引數") var s = flag.String("s", "", "string型別引數") func main() { flag.Parse() fmt.Println("-b:", *b) fmt.Println("-s:", *s) fmt.Println("其他引數:", flag.Args()) } ------------------------------------ $ go run main.go -b: false -s: 其他引數: [] ------------------------------------ $ go run main.go -b -b: true -s: 其他引數: [] ------------------------------------ $ go run main.go -b -s test others -b: true -s: test 其他引數: [others] ------------------------------------ $ go run main.go -help Usage of /tmp/go-build080353851/command-line-arguments/_obj/exe/main: -b bool型別引數 -s string string型別引數 exit status 2

2.1 定義引數

使用flag包,首先定義待解析命令列引數,也就是以”-“開頭的引數,比如這裡的 -b -s -help等。-help不需要特別指定,可以自動處理。
這裡指定了兩個引數,-b和-s:

var b = flag.Bool("b", false, "bool型別引數")
var s = flag.String("s", "", "string型別引數")

-----------------
原型:
func Bool(name string, value bool, usage string) *bool
func String(name string, value string, usage string) *string

通過flag.Bool和flag.String,建立了2個指標b和s,分別指向bool型別和string型別的變數。所以後續要通過 *b*s 使用變數值。
flag.Bool和flag.String的引數有3個,分別是命令列引數名稱,預設值,提示字串。

引數 功能
name 命令列引數名稱,比如 -b, -help
value 預設值,未顯式指定的引數,給出隱式的預設值,比如本例中-b未給出的話,*b=false
usage 提示資訊,如果給出的引數不正確或者需要檢視幫助 -help,那麼會給出這裡指定的字串

2.2 解析引數

flag使用前,必須首先解析:

flag.Parse()

2.3 使用引數

上文已經說明,通過flag方法定義好的引數變數指標,通過間接引用操作即可使用其內容:

fmt.Println("-b:", *b)
fmt.Println("-s:", *s)

2.4 未解析引數

引數中沒有能夠按照預定義的引數解析的部分,通過flag.Args()即可獲取,是一個字串切片。

fmt.Println("其他引數:", flag.Args())

需要注意的是,從第一個不能解析的引數開始,後面的所有引數都是無法解析的。即使後面的引數中含有預定義的引數:

$ go run main.go -b stop -s test others
-b: true
-s: 
其他引數: [stop -s test others]

上面例子中,解析到stop,就已經無法繼續解析了,即使後面給出了預定義好的-s,也是不能獲取出來的。