題外話
很多新手在使用一種新語言做開發語言的時候,通常不會把文件全部去熟悉一遍,即使讀過文件的也難免會有些細節也沒注意到。所以一般新手在使用新語言開發專案的時候,通常會通過搜尋引擎去解決問題。今天我要說的正是因為由於這種開發模式所帶來的對細節不注意所帶來的問題。GO 中 flag.StringVar
或者 flag.String
都獲取不到值的問題。
問題描述
在寫命令列程式(工具、server)時,對命令引數進行解析是常見的需求。各種語言一般都會提供解析命令列引數的方法或庫,以方便程式設計師使用。如果命令列引數純粹自己寫程式碼解析,對於比較複雜的,還是挺費勁的。在 go 標準庫中提供了一個包:flag
,方便進行命令列解析。在不是很瞭解 flag
的時候我們經常會這樣獲取值:
或者是這樣:
但是發現結果都不如人所願,他獲取不到值,這是為什麼呢?
解決問題
其實原因是 在 flag 中 類似 String()
或者 StringVar()
這樣的方法他僅僅是把引數名以及接收值的記憶體地址還有預設值等等引數關聯起來而已,他並沒有真正的開始從 arguments 中解析註冊到 flag。因此必須要在你定義接收好 flag 引數之前並且在訪問這些引數之前呼叫 flag.Parse()
示例程式碼:
package main
import (
"flag"
"fmt"
)
func main() {
// 定義幾個變數,用於接收命令列的引數值
var user string
var pwd string
var host string
var port int
// &user 就是接收使用者命令列中輸入的 -u 後面的引數值
// "u" 就是 -u 指定的引數
// "" 預設值
// "使用者名稱,預設為空" 說明
flag.StringVar(&user, "u", "", "使用者名稱,預設為空")
flag.StringVar(&pwd, "pwd", "", "密碼,預設為空")
flag.StringVar(&host, "h", "localhost", "主機名,預設為 localhost")
flag.IntVar(&port, "port", 3306, "duan埠號,預設3306")
// 【必須呼叫】從 arguments 中解析註冊的 flag
flag.Parse()
// 輸出結果
fmt.Printf("\n user=%v \n pwd=%v \n host=%v \n port=%v \n", user, pwd, host, port)
}
$go run 123.go -u=root -pwd=123456 -h=127.0.0.1 -port=3306
user=root
pwd=123456
host=127.0.0.1
port=3306