os.Args
程序获取运行他时给出的参数,可以通过os包来实现。先看代码:
文件:args.go
package mainimport ("fmt""os""strconv""strings")func main() {args := os.Argsarg1 := os.Args[1]// 你可以使用索引的方式来获取单个参数arg3 := os.Args[3]fmt.Println(args) // [./args a b c d]fmt.Println(arg1) // afmt.Println(arg3) // cfor idx, args := range os.Args {fmt.Println("参数" + strconv.Itoa(idx) + ":", args)}/**[./args a b c d]ac参数0: ./args参数1: a参数2: b参数3: c参数4: d*/// 输出切片的所有元素,还有更简洁的方式:fmt.Println(strings.Join(os.Args[1:], "\n"))fmt.Println(os.Args[1:])// 去掉第一个参数for idx, args := range os.Args[1:] {fmt.Println("参数:" + strconv.Itoa(idx) + ":", args)}/**hsd:testapi daysun$ go build args.gohsd:testapi daysun$ ./args a b c d[./args a b c d]ac参数0: ./args参数1: a参数2: b参数3: c参数4: dabcd[a b c d]参数:0: a参数:1: b参数:2: c参数:3: d*/}
可以看到,命令行参数包括了程序路径本身,以及通常意义上的参数。
程序中 os.Args 的类型是 []string ,也就是字符串切片。
所以可以在for循环的range中遍历,还可以用 len(os.Args) 来获取其数量。
如果不想要输出 os.Args 的第一个值,也就是可执行文件本身的信息:
for idx, args := range os.Args[1:] {...}
将range后面的切片,去掉第一个元素。
[
](https://blog.csdn.net/guanchunsheng/article/details/79612153)
flag包
flag包相比单纯的通过os.Args切片分析命令行参数,提供了更强的能力。
当我们写一些命令行小程序的时候,我们会需要解析命令行参数,以及可能会处理后面的参数。像 ls 等:
ls -a 1
要是自己写这些参数解析啥的话真是十分的难受,还好golang已经帮我们写好了相关工具。这就是flag工具包。下面我们来详细说说。
常用方法
1.flag.Usage
2.flag.Type(参数名, 默认值, 使用提示)
Type为类型 如String, Int, Uint 调用相应的flag.Sring flag.Int flag.Uint方法
方法返回相应类型的指针
3.flag.Type(指针, 参数名, 默认值, 使用提示)
与flag.Type方法基本相同,不同的是多一个指针参数,将使用传入的指针,不会再创建指针返回
4.flag.Args
返回解析完命令行参数后的其他参数,如./sh -name cqh a1 a2,将返回a1 a2
5.flag.Parse
执行解析
配置flag
配置flag主要有两类方法:
1. func XXX(name string, value xxx, usage string) *xxx2. func XXXVar(p *xxx, name string, value xxx, usage string)
其中XXX为各个类型名,有:bool、duration、float64、int64、int、uint、uint64、string等
区别:
- 直接返回指向对应类型指针并分配对应指针指向的对象,可以直接通过解引用来获取转换后的对应值。
- 指定指针指向的对象
package mainimport ("flag""fmt")// 第1种写法func main() {// 参数 默认值 说明// 返回指向对应类型指针并分配对应指针指向的对象pi := flag.Int("a", 10, "apple")flag.Parse()fmt.Printf("%v\n", *pi)/**运行:$ go run flagDemo.go -a 2020// 默认值$ go run flagDemo.go10*/}// 第2种写法 等价写法func main2() {// 指定指针指向的对象var i intflag.IntVar(&i, "a", 10, "apple")flag.Parse()fmt.Printf("%v\n", i)}
示例代码
新建 flagTest.go
package mainimport ("fmt""flag")func main() {namePtr := flag.String("name", "username", "姓名")agePtr := flag.Int("age", 18, "年龄")musclePtr := flag.Bool("muscle", true, "是否有肌肉")var email stringflag.StringVar(&email, "email", "white@taobao.com", "邮箱")flag.Parse()args := flag.Args()fmt.Println("name:", *namePtr)fmt.Println("age:", *agePtr)fmt.Println("muscle:", *musclePtr)fmt.Println("email:", email)fmt.Println("args:", args)}
编译运行
$ go build flagTest.go$ ./flagTest -hUsage of ./flagTest:-age int年龄 (default 18)-email string邮箱 (default "white@taobao.com")-muscle是否有肌肉 (default true)-name string姓名 (default "username")#默认值$ ./flagTestname: usernameage: 18muscle: trueemail: white@taobao.comargs: []# 命令行参数$ ./flagTest -name 肌肉男 -age 20 -email 123@qq.com 哈哈 呵呵 嘿嘿name: 肌肉男age: 20muscle: trueemail: 123@qq.comargs: [哈哈 呵呵 嘿嘿]
NewFlagSet
使用 NewFlagSet 函数声明一个子命令, 然后为这个子命令定义一个专用的 flag。
对于不同的子命令,我们可以定义不同的 flag。
子命令应作为程序的第一个参数传入。
package mainimport ("flag""fmt""os")func main() {// 声明一个子命令fooCmdfooCmd := flag.NewFlagSet("foo", flag.ExitOnError)// 子命令专用tagfooEnable := fooCmd.Bool("enable", false, "enable")fooName := fooCmd.String("name", "", "name")barCmd := flag.NewFlagSet("bar", flag.ExitOnError)barLevel := barCmd.Int("level", 0, "level")if len(os.Args) < 2 {fmt.Println("expected 'foo' or 'bar' subcommands")os.Exit(1)}switch os.Args[1] {case "foo":fooCmd.Parse(os.Args[2:])fmt.Println("subcommand 'foo'")fmt.Println(" enable:", *fooEnable)fmt.Println(" name:", *fooName)fmt.Println(" tail:", fooCmd.Args())case "bar":barCmd.Parse(os.Args[2:])fmt.Println("subcommand 'bar'")fmt.Println(" level:", *barLevel)fmt.Println(" tail:", barCmd.Args())default:fmt.Println("expected 'foo' or 'bar' subcommands")os.Exit(1)}}
#编译$ go build flagNewFlagSet.go#调用 foo 子命令$ ./flagNewFlagSet foo -enable -name=joe a1 a2subcommand 'foo'enable: truename: joetail: [a1 a2]#调用 bar 子命令$ ./flagNewFlagSet bar -level 8 a1subcommand 'bar'level: 8tail: [a1]# bar 不接受 foo 的 flag(enable)参数$ ./flagNewFlagSet bar -nable a1flag provided but not defined: -nableUsage of bar:-level intlevel
总结
- flag 主要提供了一种参数解析方式,可以根据以注册命令参数, 解析不同的输出对象, 以获取所需信息。
- flag 主要包含
- 对象的定义及工厂函数
- 各类型参数注册方法
- 信息获取函数
模块默认提供命令行的快捷方法。
参考:
