Go語言命令列程式和他們的引數

程式設計師的貓發表於2020-07-23

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輸出切片的格式
*/

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
定義引數

使用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,那麼會給出這裡指定的字串

解析引數

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

flag.Parse()

使用引數

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

fmt.Println("-b:", *b)
fmt.Println("-s:", *s)
未解析引數

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

fmt.Println("其他引數:", flag.Args())
1
需要注意的是,從第一個不能解析的引數開始,後面的所有引數都是無法解析的。即使後面的引數中含有預定義的引數:

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

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

本作品採用《CC 協議》,轉載必須註明作者和本文連結

你還差得遠吶!

相關文章