12.4 從命令行讀取參數

12.4.1 os 包

os 包中有一個 string 類型的切片變量 os.Args,用來處理一些基本的命令行參數,它在程序啓動後讀取命令行輸入的參數。來看下面的打招呼程序:

示例 12.11 os_args.go

// os_args.go
package main

import (
    "fmt"
    "os"
    "strings"
)

func main() {
    who := "Alice "
    if len(os.Args) > 1 {
        who += strings.Join(os.Args[1:], " ")
    }
    fmt.Println("Good Morning", who)
}

我們在 IDE 或編輯器中直接運行這個程序輸出:Good Morning Alice

我們在命令行運行 os_args or ./os_args 會得到同樣的結果。

但是我們在命令行加入參數,像這樣:os_args John Bill Marc Luke,將得到這樣的輸出:Good Morning Alice John Bill Marc Luke

這個命令行參數會放置在切片 os.Args[] 中(以空格分隔),從索引1開始(os.Args[0] 放的是程序本身的名字,在本例中是 os_args)。函數 strings.Join 以空格爲間隔連接這些參數。

練習 12.5hello_who.go

寫一個"Hello World"的變種程序:把人的名字作爲程序命令行執行的一個參數,比如: hello_who Evan Michael Laura 那麼會輸出Hello Evan Michael Laura!

12.4.2 flag 包

flag 包有一個擴展功能用來解析命令行選項。但是通常被用來替換基本常量,例如,在某些情況下我們希望在命令行給常量一些不一樣的值。(參看 19 章的項目)

在 flag 包中一個 Flag 被定義成一個含有如下字段的結構體:

type Flag struct {
    Name     string // name as it appears on command line
    Usage    string // help message
    Value    Value  // value as set
    DefValue string // default value (as text); for usage message
}

下面的程序 echo.go 模擬了 Unix 的 echo 功能:

package main

import (
    "flag" // command line option parser
    "os"
)

var NewLine = flag.Bool("n", false, "print newline") // echo -n flag, of type *bool

const (
    Space   = " "
    Newline = "\n"
)

func main() {
    flag.PrintDefaults()
    flag.Parse() // Scans the arg list and sets up flags
    var s string = ""
    for i := 0; i < flag.NArg(); i++ {
        if i > 0 {
            s += " "
            if *NewLine { // -n is parsed, flag becomes true
                s += Newline
            }
        }
        s += flag.Arg(i)
    }
    os.Stdout.WriteString(s)
}

flag.Parse() 掃描參數列表(或者常量列表)並設置 flag, flag.Arg(i) 表示第i個參數。Parse() 之後 flag.Arg(i) 全部可用,flag.Arg(0) 就是第一個真實的 flag,而不是像 os.Args(0) 放置程序的名字。

flag.Narg() 返回參數的數量。解析後 flag 或常量就可用了。 flag.Bool() 定義了一個默認值是 false 的 flag:當在命令行出現了第一個參數(這裏是 "n"),flag 被設置成 true(NewLine 是 *bool 類型)。flag 被解引用到 *NewLine,所以當值是 true 時將添加一個 newline("\n")。

flag.PrintDefaults() 打印 flag 的使用幫助信息,本例中打印的是:

-n=false: print newline

flag.VisitAll(fn func(*Flag)) 是另一個有用的功能:按照字典順序遍歷 flag,並且對每個標籤調用 fn (參考 15.8 章的例子)

當在命令行(Windows)中執行:echo.exe A B C,將輸出:A B C;執行 echo.exe -n A B C,將輸出:

A
B
C

每個字符的輸出都新起一行,每次都在輸出的數據前面打印使用幫助信息:-n=false: print newline

對於 flag.Bool 你可以設置布爾型 flag 來測試你的代碼,例如定義一個 flag processedFlag:

var processedFlag = flag.Bool(“proc”, false, “nothing processed yet”)

在後面用如下代碼來測試:

if *processedFlag { // found flag -proc
    r = process()
}

要給 flag 定義其它類型,可以使用 flag.Int()flag.Float64flag.String()

在第 15.8 章你將找到一個具體的例子。

鏈接

results matching ""

    No results matching ""