os.Args
程序获取运行他时给出的参数,可以通过os包来实现。先看代码:
文件:args.go
package main
import (
"fmt"
"os"
"strconv"
"strings"
)
func main() {
args := os.Args
arg1 := os.Args[1]
// 你可以使用索引的方式来获取单个参数
arg3 := os.Args[3]
fmt.Println(args) // [./args a b c d]
fmt.Println(arg1) // a
fmt.Println(arg3) // c
for idx, args := range os.Args {
fmt.Println("参数" + strconv.Itoa(idx) + ":", args)
}
/**
[./args a b c d]
a
c
参数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.go
hsd:testapi daysun$ ./args a b c d
[./args a b c d]
a
c
参数0: ./args
参数1: a
参数2: b
参数3: c
参数4: d
a
b
c
d
[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) *xxx
2. func XXXVar(p *xxx, name string, value xxx, usage string)
其中XXX为各个类型名,有:bool、duration、float64、int64、int、uint、uint64、string等
区别:
- 直接返回指向对应类型指针并分配对应指针指向的对象,可以直接通过解引用来获取转换后的对应值。
- 指定指针指向的对象
package main
import (
"flag"
"fmt"
)
// 第1种写法
func main() {
// 参数 默认值 说明
// 返回指向对应类型指针并分配对应指针指向的对象
pi := flag.Int("a", 10, "apple")
flag.Parse()
fmt.Printf("%v\n", *pi)
/**
运行:
$ go run flagDemo.go -a 20
20
// 默认值
$ go run flagDemo.go
10
*/
}
// 第2种写法 等价写法
func main2() {
// 指定指针指向的对象
var i int
flag.IntVar(&i, "a", 10, "apple")
flag.Parse()
fmt.Printf("%v\n", i)
}
示例代码
新建 flagTest.go
package main
import (
"fmt"
"flag"
)
func main() {
namePtr := flag.String("name", "username", "姓名")
agePtr := flag.Int("age", 18, "年龄")
musclePtr := flag.Bool("muscle", true, "是否有肌肉")
var email string
flag.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 -h
Usage of ./flagTest:
-age int
年龄 (default 18)
-email string
邮箱 (default "white@taobao.com")
-muscle
是否有肌肉 (default true)
-name string
姓名 (default "username")
#默认值
$ ./flagTest
name: username
age: 18
muscle: true
email: white@taobao.com
args: []
# 命令行参数
$ ./flagTest -name 肌肉男 -age 20 -email 123@qq.com 哈哈 呵呵 嘿嘿
name: 肌肉男
age: 20
muscle: true
email: 123@qq.com
args: [哈哈 呵呵 嘿嘿]
NewFlagSet
使用 NewFlagSet 函数声明一个子命令, 然后为这个子命令定义一个专用的 flag。
对于不同的子命令,我们可以定义不同的 flag。
子命令应作为程序的第一个参数传入。
package main
import (
"flag"
"fmt"
"os"
)
func main() {
// 声明一个子命令fooCmd
fooCmd := flag.NewFlagSet("foo", flag.ExitOnError)
// 子命令专用tag
fooEnable := 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 a2
subcommand 'foo'
enable: true
name: joe
tail: [a1 a2]
#调用 bar 子命令
$ ./flagNewFlagSet bar -level 8 a1
subcommand 'bar'
level: 8
tail: [a1]
# bar 不接受 foo 的 flag(enable)参数
$ ./flagNewFlagSet bar -nable a1
flag provided but not defined: -nable
Usage of bar:
-level int
level
总结
- flag 主要提供了一种参数解析方式,可以根据以注册命令参数, 解析不同的输出对象, 以获取所需信息。
- flag 主要包含
- 对象的定义及工厂函数
- 各类型参数注册方法
- 信息获取函数
模块默认提供命令行的快捷方法。
参考: