题外话
很多新手在使用一种新语言做开发语言的时候,通常不会把文档全部去熟悉一遍,即使读过文档的也难免会有些细节也没注意到。所以一般新手在使用新语言开发项目的时候,通常会通过搜索引擎去解决问题。今天我要说的正是因为由于这种开发模式所带来的对细节不注意所带来的问题。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(" user=%v pwd=%v host=%v port=%v ", 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