最近在使用go开发cli(command-line-interface)时,通过对于官方文档以及他人博客的学习,在此写下个人认为更适合自己往后回顾的关于flag的使用说明。
工欲善其事必先利其器,先奉上flag官方文档解析
Demo0:
package main
import (
"fmt"
"flag"
)
func main() {
t1 := flag.Int("w",0,"demo test")
t2 := flag.String("a","Hello","demo test")
flag.Parse()
fmt.Println("t1 is ", *t1)
fmt.Println("t2 is ", *t2)
fmt.Printf("There is %d non-flag\n", flag.NArg())
for i,arg := range flag.Args() {
fmt.Printf("%d is %s\n",i+1, arg)
}
}
从main往下看:第一句代表我们需要一个w
的命令行参数,这个参数接收int类型的值。第二句同理,只是int换成了string。紧跟后面的0
是我们设置的默认值,demo test
则是我们给这个参数作用的说明,可以通过调用 flag.Usage() 看到。flag.Parse()代表我们开始解析参数,在Parse以后,我们是不允许再添加参数的,也就是说,我们不能写了Parse之后再写一个flag.Int()
。flag.NArg()用来输出non-flag参数的个数。在讲non-flag前,我们先看命令行标签格式:
-flag
-flag=x
-flag x // 只有非boolean标签能这么用
// 减号可以使用一个或者两个,效果是一样的。
一般而言,我们定义了的参数便是flag参数,使用的形式便是上述形式。而我们没有定义的,又没有使用上述格式的,我们一般便称其为non-flag参数。可能有人有疑问,以Demo0代码为例,那 -p 应该算作什么?这里要分两种情况:
go run demo0.go -w 10 -a hahaha -p start
此时的-p便为已使用但是未定义的flag参数
go run demo0.go -w 10 -a hahaha start -p 666
此时的-p便是non-flag参数。此时的重点就是,flag参数的解析在碰到第一个non-flag参数便会停止,即从第一个non-flag开始,后面出现的所有参数都将被认为是non-flag,不论你是否符合要求的命令行标签格式。所以,以上述命令为例,non-flag参数有三个 : start 、 -p、666
,所以如果你希望在non-flag后面仍然能像在non-flag之前一般处理(比如把666赋给p),可能需要做更多额外的处理工作才能完成。
Demo1:
package main
import (
"fmt"
"flag"
)
func main() {
var t1 int
flag.IntVar(&t1, "t", 0, "sample 1")
t2 := flag.Int("t", 0, "sample 2")
flag.Parse()
}
上述Demo目的在于讲明flag.xxxVar 与 flag.xxx 间的区别。通过官方文档可以获悉,flag.xxxVar需要你传入一个指针作为参数,而flag.xxx则是返回一个指针值。具体应用场景大家见仁见智。于我个人而言,如果所需参数的作用是全局的,我会选择使用flag.xxxVar绑定到一个全局变量之上,如果只是局部作用,比如作为后续行为的一个选择条件之一,那么一般我会采用flag.xxx的形式
Demo2 :
package main
import (
"fmt"
"flag"
"os"
)
func main() {
var t1 int
flag.IntVar(&t1, "t", 0, "1")
t2 := flag.Int("t", 0, "2")
flag.Parse()
// 如果你希望使用自己写的usage
// flag.Usage = usage
if t1 != 1 {
flag.Usage()
}
}
func usage() {
fmt.Fprintf(os.Stderr, "That's good")
}
这里主要讲解flag.Usage()的使用,实际上这个函数便是将我们定义参数时写的关于参数的说明进行输出。一般而言,此函数一般在用户使用错误时作为提示给出。根据文档,flag.Usage() 默认 输出到 os.Stderr。我们也可以将之用自己的函数替代,从而打造更加个性化的提示。
End
实际上结合上述Demo已经能够简单的利用flag进行参数解析,如果希望追求更为复杂使用的使用方式,不建议使用flag包,不妨看看pflag或者goptions,相信你能有更加棒的收获。