这里填写标题
1. golang 命令行参数解析
golang 的命令行参数解析, 推荐两种。一个是
os.Args
, 另一个是使用flag
模块。
1.1. os.Args
package main
import (
"fmt"
"os"
)
func main() {
args := os.Args
// 使用 go run xx.go 1 2 3 xx aaa bbb ccc ddd eee
// 那么 args 就是 [xx.exe 1 2 3 xx aaa bbb ccc ddd eee]
// 并且全部是 string 类型
fmt.Println(args)
}
效果:
$ ./out 1 2 3 xx aaa bbb ccc ddd eee
[./out 1 2 3 xx aaa bbb ccc ddd eee]
1.2. flag
flag
模块可以支持使用关键字的方式指定参数。
package main
import (
"flag"
"fmt"
)
func main() {
//flag.Type 里面接受三个参数, 指定的名字, 默认值, 描述信息
Name := flag.String("name", "mashiro", "姓名")
Age := flag.Int("age", 16, "年龄")
has_gf := flag.Bool("has_gf", false, "有女朋友? ")
//解析
flag.Parse()
/*
我们在命令行中便可以通过 name satori age 16 has_gf false 这种方式指定
当然还可以使用其他方式比如 --name satori, -name satori, --name=satori,-name=satori
*/
//但是注意: 得到的 Name、Age、has_gf 都是指针
fmt.Println(*Name, *Age, *has_gf)
}
效果:
$ ./out --name koishi -age=15 has_gf false
koishi 15 false
$ ./out -h
Usage of ./out:
-age int
年龄 (default 16)
-has_gf
有女朋友?
-name string
姓名 (default "mashiro")
1.2.1. flag 的其他参数
package main
import (
"flag"
"fmt"
)
func main() {
Name := flag.String("name", "mashiro", "姓名")
Age := flag.Int("age", 16, "年龄")
has_gf := flag.Bool("has_gf", false, "有女朋友? ")
flag.Parse()
fmt.Println(*Name, *Age, *has_gf)
//命令行后的其他参数, 是一个 []string 类型
fmt.Println(flag.Args())
//命令行后的其他参数个数
fmt.Println(flag.NArg())
//命令行使用的参数个数
fmt.Println(flag.NFlag())
}
效果:
$ ./out --name koishi -age=15 a b c 1
koishi 15 false
[a b c 1]
4
2
我们后面多指定了
a b c 1
, 所以可以通过flag.Args
来获取,flag.NArgs
就是多指定的参数个数,flag.NFlag
则是我们在命令行, 通过指定关键字的方式指定的参数个数, 这里是2
, 因为has_gf
我们没有指定, 但即便如此也是打印了默认值的。
flag
模块还可以使用一种方式, flag.TypeVar
, 这和 flag.Type
是基本类似的。
package main
import (
"flag"
"fmt"
)
func main() {
var Name string
var Age int
var has_gf bool
flag.StringVar(&Name, "name", "mashiro", "姓名")
flag.IntVar(&Age, "age", 16, "年龄")
flag.BoolVar(&has_gf, "has_gf", false, "有女朋友? ")
flag.Parse()
fmt.Println(Name, Age, has_gf)
fmt.Println(flag.Args())
fmt.Println(flag.NArg())
fmt.Println(flag.NFlag())
}
flag.Type
是直接返回一个指针, flag.TypeVar
则是需要先声明变量, 然后把指针传进去, 至于后面的参数、以及结果都是一样的。
1.2.2. 其它
1.2.2.1. 命令行解析出来后对应的是代码中的变量, 在 flag
包中获取的变量支持的类型有:
-
- bool
-
- time.Duration
-
- float64
-
- int
-
- int64
-
- string
-
- uint
-
- uint64
1.2.2.2. 将命令行输入值赋值到对应变量的方法:
- 1)bool 类型对应:
Bool(name string, value bool, usage string) *bool
BoolVar(p *bool, name string, value bool, usage string)
- 2)time.Duration 类型对应:
Duration(name string, value time.Duration, usage string) *time.Duration
DurationVar(p *time.Duration, name string, value time.Duration, usage string)
- 3)float64 类型对应:
Float64(name string, value float64, usage string) *float64
Float64Var(p *float64, name string, value float64, usage string)
- 4)int 类型对应:
Int(name string, value int, usage string) *int
IntVar(p *int, name string, value int, usage string)
- 5)int64 类型对应:
Int64(name string, value int64, usage string) *int64
Int64Var(p *int64, name string, value int64, usage string)
- 6)string 类型对应:
String(name string, value string, usage string) *string
StringVar(p *string, name string, value string, usage string)
- 7)uint 类型对应:
Uint(name string, value uint, usage string) *uint
UintVar(p *uint, name string, value uint, usage string)
- 8)uint64 类型对应:
Uint64(name string, value uint64, usage string) *uint64
Uint64Var(p *uint64, name string, value uint64, usage string)
1.2.2.3. 默认值和用法说明:
获取命令行参数接口中 value 参数为默认值, usage 参数为命令行使用说明。用 programname + -h
可以看到 usage 对应的字符串。
下面以一个例子来看看 flag
的使用方法:
func main() {
var lang = flag.String("lang", "golang", "the lang of the program")
var age = flag.Int64("age", 18, "the age of the user")
var safemod = flag.Bool("safemod", true, "whether using safemode")
flag.Parse()
fmt.Println("lang is: ", *lang)
fmt.Println("age is: ", *age)
fmt.Println("safemod is: ", *safemod)
}
直接运行结果如下:
lang is: golang
age is: 18
safemod is: true
-h
显示如下:
Usage of test.exe:
-age int
the age of the user (default 18)
-lang string
the lang of the program (default "golang")
-safemod
whether using safemode (default true)
从例子可以看出, 绑定好变量后, 直接调用 flag.Parse()
方法, 就可以解析出命令行参数了。这个比 C++ 中的 getopt
来的简单直观很多。