12.4.1 os包
os包中有一个string类型的切片变量os.Args
,其用来处理一些基本的命令行参数,它在程序启动后读取命令行输入的参数。来看下面的打招呼程序:
示例 12.11 os_args.go:
// os_args.go
package main
import (
"fmt"
"os"
"strings"
)
func main() {
who := "Alice "
if len(os.Args) > 1 {
who += strings.Join(os.Args[1:], " ")
}
fmt.Println("Good Morning", who)
}
我们在IDE或编辑器中直接运行这个程序输出:Good Morning Alice
我们在命令行运行os_args or ./os_args
会得到同样的结果。
但是我们在命令行加入参数,像这样:os_args John Bill Marc Luke
,将得到这样的输出:Good Morning Alice John Bill Marc Luke
这个命令行参数会放置在切片os.Args[]
中(以空格分隔),从索引1开始(os.Args[0]
放的是程序本身的名字,在本例中是os_args
)。函数strings.Join
函数用来连接这些参数,以空格作为间隔。
练习 12.5:hello_who.go 写一个"Hello World"的变种程序:把人的名字作为程序命令行执行的一个参数,比如:hello_who Evan Michael Laura
那么会输出Hello Evan Michael Laura
!
12.4.2 flag包
flag包有一个扩展功能用来解析命令行选项。但是通常被用来替换基本常量,例如,在某些情况下我们希望在命令行给常量一些不一样的值。(参看19章的项目)
在flag包中一个Flag被定义成一个含有如下字段的结构体:
type Flag struct {
Name string // name as it appears on command line
Usage string // help message
Value Value // value as set
DefValue string // default value (as text); for usage message
}
下面的程序echo.go
模拟了Unix的echo功能:
package main
import (
"flag" // command line option parser
"os"
)
var NewLine = flag.Bool("n", false, "print newline") // echo -n flag, of type *bool
const (
Space = " "
Newline = "
"
)
func main() {
flag.PrintDefaults()
flag.Parse() // Scans the arg list and sets up flags
var s string = ""
for i := 0; i < flag.NArg(); i++ {
if i > 0 {
s += " "
if *NewLine { // -n is parsed, flag becomes true
s += Newline
}
}
s += flag.Arg(i)
}
os.Stdout.WriteString(s)
}
flat.Parse()
扫描参数列表(或者常量列表)并设置flag, flag.Arg(i)
表示第i个参数。Parse()
之后所有flag.Arg(i)
全部可用,flag.Arg(0)
就是第一个真实的flag,而不是像os.Args(o)
放置程序的名字。
flag.Narg()
返回参数的数量。解析后flag或常量就可用了。flag.Bool()
定义了一个默认值是false
的flag:当在命令行出现了第一个参数(这里是"n"),flag被设置成"true"(NewLine是*bool
类型)。如果*NewLine
表示对flag解引用,所以当值是true
时将添加一个newline。
flag.PrintDefaults()
打印flag的使用帮助信息,本例中打印的是:
-n=false: print newline
flag.VisitAll(fn func(*Flag))
是另一个有用的功能:按照字典顺序遍历flag,并且对每个标签调用fn(参考15.8章的例子)
当在命令行(Windows)中执行:echo.exe A B C
,将输出:A B C
;执行echo.exe -n A B C
,将输出:
A
B
C
每个字符的输出都新起一行,每次都在输出的数据前面打印使用帮助信息:-n=false: print newline
对于flag.Bool
你可以设置布尔型flag来测试你的代码,例如定义一个flag processedFlag
:
var processedFlag = flag.Bool(“proc”, false, “nothing processed yet”)
在后面用如下代码来测试:
if *processedFlag { // found flag -proc
r = process()
}
要给flag定义其它类型,可以使用flag.Int()
,flag.Float64
,flag.String()
在15.8章你将找到一个完成的例子。