題外話
很多新手在使用一種新語言做開發語言的時候,通常不會把文檔全部去熟悉一遍,即使讀過文檔的也難免會有些細節也沒注意到。所以一般新手在使用新語言開發項目的時候,通常會通過搜索引擎去解決問題。今天我要說的正是因為由於這種開發模式所帶來的對細節不注意所帶來的問題。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
