ThinkChat🤖让你学习和工作更高效,注册即送10W Token,即刻开启你的AI之旅 广告
## 12.4.1 os包 os包中有一个string类型的切片变量`os.Args`,其用来处理一些基本的命令行参数,它在程序启动后读取命令行输入的参数。来看下面的打招呼程序: 示例 12.11 [os_args.go](https://github.com/Unknwon/the-way-to-go_ZH_CN/blob/master/eBook/examples/chapter_12/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](https://github.com/Unknwon/the-way-to-go_ZH_CN/blob/master/eBook/exercises/chapter_12/hello_who.go) 写一个"Hello World"的变种程序:把人的名字作为程序命令行执行的一个参数,比如:`hello_who Evan Michael Laura` 那么会输出`Hello Evan Michael Laura`! ## [](https://github.com/Unknwon/the-way-to-go_ZH_CN/blob/master/eBook/12.4.md#1242-flag包)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 = "\n" ) 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章你将找到一个完成的例子。