原文:CalliCoder — Go Command-line flags/options
命令列程式通常會接受來自使用者的旗標或選項來自訂指令的執行。旗標是在執行指令時加在指令名稱後的鍵值對。
Go 允許你使用標準函式庫中的 flags
package 來接收命令列旗標。在本文中,你將學到如何為命令列程式接收旗標。
Go 的命令列旗標
要接收命令列旗標,你需要定義旗標以便從命令列取值。你可以透過多種方式做到:
- 使用
flag.String()
、flag.Bool()
、flag.Int()
等方法定義旗標。 - 使用
flag.StringVar()
,flag.IntVar()
等方法將現有變數綁定到命令列旗標。 - 透過宣告一個實作
flag.Value
介面的類型來建立自訂旗標,然後使用flag.Var()
方法將自訂類型的變數與命令列旗標綁定。
讓我們在以下範例中看看前兩種方法。我們會在其他範例看到第三種方法。
package main
import (
"flag"
"fmt"
"strings"
)
func main() {
// Declare a string flag called name with a default value ("Guest") and a help message
name := flag.String("name", "Guest", "specify your name")
// Declare a flag called age with default value of 0 and a help message
age := flag.Int("age", 0, "specify your age")
// Bind the command-line flag with an existing variable
var country string
flag.StringVar(&country, "country", "", "enter your country")
// Enable command-line parsing
flag.Parse()
fmt.Printf("Hello %s\n", *name)
fmt.Printf("Your age is %d\n", *age)
fmt.Printf("Your are from %s\n", country)
}
# Build the program
$ go build command-line-flags.go
使用 -h 或 --help 旗標來取得命令列程式的輔助說明
$ ./command-line-flags -h
Usage of ./command-line-flags:
-age int
specify your age
-country string
enter your country
-name string
specify your name (default "Guest")
使用空格分隔的鍵值對提供旗標
$ ./command-line-flags -name Rajeev -age 28 -country India
Hello Rajeev
Your age is 28
Your are from India
使用 鍵=值 的格式提供旗標
$ ./command-line-flags -name=Rajeev -age=28 -country="United Kingdom"
Hello Rajeev
Your age is 28
Your are from United Kingdom
如果未指定,則旗標使用預設值
$ ./command-line-flags -age=24 -country="United States"
Hello Guest
Your age is 24
Your are from United States
建立自訂命令列旗標
以下範例示範了如何建立自訂旗標。在這個範例中,我們定義並解析以逗號分隔的命令列旗標。
package main
import (
"flag"
"fmt"
"strings"
)
// A custom type that implements the flag.Value interface
type hobbies []string
func (h *hobbies) String() string {
return fmt.Sprint(*h)
}
func (h *hobbies) Set(value string) error {
for _, hobby := range strings.Split(value, ",") {
*h = append(*h, hobby)
}
return nil
}
func main() {
// Define a custom flag
var hobbiesFlag hobbies
flag.Var(&hobbiesFlag, "hobbies", "comma separated list of hobbies")
// Enable command-line parsing
flag.Parse()
fmt.Printf("Your hobbies are: ")
for _, hobby := range hobbiesFlag {
fmt.Printf("%s ", hobby)
}
fmt.Println()
}
# Output
$ ./command-line-flags -hobbies=Sports,Photography,Coding
Your hobbies are: Sports Photography Coding
使用旗標 package 處理位置引數
flag.Parse()
函數會持續解析它遇到的旗標,直到它偵測到非旗標引數(位置引數)。旗標 package 透過 Args()
和 Arg()
函數讓你可以使用位置引數。
請注意,旗標 package 要求所有旗標都出現在位置引數之前。否則,旗標會被直譯為位置引數。
讓我們來看一個位置引數的範例。假設我們正在撰寫一個程式,用來在檔案中的起始行號到結束行號搜尋給定的關鍵字清單。在以下範例中,我們接受作為旗標的起始和結束行號,以及作為位置引數的關鍵字清單:
package main
import (
"flag"
"fmt"
)
func main() {
s := flag.Int("s", 0, "start line number")
t := flag.Int("t", 0, "end line number")
// Enable command-line parsing
flag.Parse()
fmt.Printf("Search file from line number %d to %d\n", *s, *t)
// Read all the positional arguments
fmt.Println("for keywords:", flag.Args())
// Read the i'th positional argument
i := 0
fmt.Printf("The keyword at index %d: %v\n", i, flag.Arg(i))
}
以下是向程式提供旗標和非旗標引數的方法:
$ go build command-line-flags.go
$ ./command-line-flags -s 1 -t 100 Go Java
Search file from line number 1 to 100
for keywords: [Go Java]
The keyword at index 0: Go
你必須在位置引數之前指定旗標。否則,旗標也會被直譯為位置引數:
$ ./command-line-flags Go Java -s 1 -t 100
Search file from line number 0 to 0
for keywords: [Go Java -s 1 -t 100]
The keyword at index 0: Go