Go語言標(biāo)準(zhǔn)庫中的flag包專門用于接收和解析命令參數(shù)。
我們提供的服務(wù)有:網(wǎng)站制作、做網(wǎng)站、微信公眾號開發(fā)、網(wǎng)站優(yōu)化、網(wǎng)站認(rèn)證、古交ssl等。為上千余家企事業(yè)單位解決了網(wǎng)站和推廣的問題。提供周到的售前咨詢和貼心的售后服務(wù),是有科學(xué)管理、有技術(shù)的古交網(wǎng)站制作公司從命令行接收參數(shù)并打印出來:
package main
import (
"flag"
"fmt"
)
var name string
func init() {
flag.StringVar(&name, "name", "Nobody", "請設(shè)置名字")
}
func main() {
flag.Parse()
fmt.Printf("Hello, %s!\n", name)
}
函數(shù)flag.StringVar接受4個參數(shù):
還有一個函數(shù)flag.String和flag.StringVar類似。就是沒有第一個參數(shù)了,而是直接返回一個已經(jīng)分配好的用于存儲命令參數(shù)值的地址。
package main
import (
"flag"
"fmt"
)
var name string
func init() {
name = *flag.String("name", "Nobody", "請設(shè)置名字")
}
func main() {
flag.Parse()
fmt.Printf("Hello, %s!\n", name)
}
函數(shù)flag.Parse用于真正解析命令參數(shù),并把它們的值賦給相應(yīng)的變量。
該函數(shù)的調(diào)用必須在所有命令參數(shù)的聲明和設(shè)置之后,并且在讀取任何命令參數(shù)值之前。
也就是像例子里做的,把參數(shù)設(shè)置的語句放在init函數(shù)里先執(zhí)行,然后把flag.Parse放在main函數(shù)的開頭,在調(diào)用使用命令行參數(shù)的語句之前。
在上面的例子中,執(zhí)行的時候帶上-h或者--help參數(shù),就能看到如下的使用說明:
PS G:\Steed\Documents\Go\src\Go36\article02\example01> go run main.go --help
Usage of C:\Users\Steed\AppData\Local\Temp\go-build897600374\command-line-arguments\_obj\exe\main.exe:
-name string
請設(shè)置名字 (default "Nobody")
exit status 2
PS G:\Steed\Documents\Go\src\Go36\article02\example01>
輸出的第一行在Usage of后面一長串的路徑,是go run命令構(gòu)建上述命令源碼文件時臨時生成的可執(zhí)行文件的完整路徑。如果是編譯之后再執(zhí)行,就是可執(zhí)行文件的相對路徑,就沒那么難看了。
并且這一行的說明內(nèi)容是可以自定制的,接下來就是通過包提供的方法對這行說明進(jìn)行自定制。這3種方法是一層一層更加接近底層的調(diào)用的。
最簡單的一種定制方式就是對變量flag.Usage重新賦值。為該變量定義一個函數(shù),在要打印說明的時候,其實就是調(diào)用執(zhí)行了這個方法:
package main
import (
"flag"
"fmt"
"os"
)
var name string
func init() {
// 下面2句語句的順序隨意
flag.StringVar(&name, "name", "Nobody", "請設(shè)置名字")
flag.Usage = func() {
fmt.Fprintf(os.Stderr, "Usage of %s\n", "Say Hello")
flag.PrintDefaults()
}
}
func main() {
flag.Parse()
fmt.Printf("Hello, %s!\n", name)
}
flag.Usage的賦值必須在調(diào)用flag.Parse()之前。
在調(diào)用flag包中的一些函數(shù)(比如StringVar、Parse等等)的時候,實際上是在調(diào)用flag.CommandLine變量的對應(yīng)方法。
flag.CommandLine相當(dāng)于默認(rèn)情況下的命令參數(shù)容?。通過對flag.CommandLine重新賦值,就可以更深層次地定制當(dāng)前命令源碼文件的參數(shù)使用說明。
僅修改之前的init函數(shù)部分,去掉flag.Usage的賦值語句,改為通過對flag.CommandLine賦值來進(jìn)行定制:
func init() {
// flag.CommandLine對象的創(chuàng)建必須在前面執(zhí)行
flag.CommandLine = flag.NewFlagSet("", flag.ExitOnError)
//flag.CommandLine = flag.NewFlagSet("", flag.PanicOnError)
flag.CommandLine.Usage = func() {
fmt.Fprintf(os.Stderr, "Usage of %s\n", "Say Hello")
flag.PrintDefaults()
}
flag.StringVar(&name, "name", "Nobody", "請設(shè)置名字")
}
這樣修改后的效果和之前完全一致。這里主要出分離出了下面這句:
flag.CommandLine = flag.NewFlagSet("", flag.ExitOnError)
這句的第一個參數(shù)應(yīng)該是沒有用的了,這里傳入空字符串。
第二個參數(shù)可以是一下的3個常量:
const (
ContinueOnError ErrorHandling = iota // Return a descriptive error.
ExitOnError // Call os.Exit(2).
PanicOnError // Call panic with a descriptive error.
)
定義在解析遇到問題后,是執(zhí)行何種操作。默認(rèn)的就是ExitOnError,所以在--help執(zhí)行打印說明后,最后一行會出現(xiàn)“exit status 2”,以狀態(tài)碼2退出。
這里可以根據(jù)需要定制為拋出Panic。
這里的代碼上上面的例子差不多,依然是調(diào)用flag.NewFlagSet()創(chuàng)建命令參數(shù)容器。不過這次把容器賦值給自定義的變量:
package main
import (
"flag"
"fmt"
"os"
)
var name string
var cmdLine = flag.NewFlagSet("cmdLine Say Hello", flag.ExitOnError)
func init() {
cmdLine.StringVar(&name, "name", "Nobody", "請設(shè)置名字")
}
func main() {
cmdLine.Parse(os.Args[1:])
fmt.Printf("Hello, %s!\n", name)
}
首先通過命令var cmdLine = flag.NewFlagSet("cmdLine Say Hello", flag.ExitOnError)
創(chuàng)建了私有的命令參數(shù)容器。
然后,之后其他所有方法的調(diào)用都通過這個變量來調(diào)用的。
上面這樣做之后,就完全脫離了flag.CommandLine。而是使用 *flag.FlagSet 類型的變量 cmdLine 進(jìn)行各種調(diào)用了。該類型擁有很多方法,可以繼續(xù)探索。
主要是可以更靈活地定制命令參數(shù)容?。并且你的定制完全不會影響到全局變量flag.CommandLine。
創(chuàng)新互聯(lián)www.cdcxhl.cn,專業(yè)提供香港、美國云服務(wù)器,動態(tài)BGP最優(yōu)骨干路由自動選擇,持續(xù)穩(wěn)定高效的網(wǎng)絡(luò)助力業(yè)務(wù)部署。公司持有工信部辦法的idc、isp許可證, 機(jī)房獨(dú)有T級流量清洗系統(tǒng)配攻擊溯源,準(zhǔn)確進(jìn)行流量調(diào)度,確保服務(wù)器高可用性。佳節(jié)活動現(xiàn)已開啟,新人活動云服務(wù)器買多久送多久。