Skip to content

Commit

Permalink
Merge branch 'master' into master
Browse files Browse the repository at this point in the history
  • Loading branch information
hantmac committed May 8, 2019
2 parents 9930cc6 + 6f19b6d commit 91fa337
Showing 1 changed file with 45 additions and 78 deletions.
123 changes: 45 additions & 78 deletions eBook/chapter8/08.2.md
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@

# **flag包**

标识是特殊格式的字符串,可以传入程序以控制其行为。如果希望支持多个标识,那么自己单独处理标识可能会很困难。因此,如果你正在开发Unix系统命令行实用程序,你会发现flag包非常有趣和有用。在它的其他特性中,flag包对命令行参数和选项的顺序没有任何假设,并且在命令行实用程序执行过程中出现错误时,它会打印有用的信息。

flag包的最大好处是,它是*Go*标准库的一部分,意味着它经过了广泛的测试和调试
flag包的最大好处是,它是*Go*标准库的一部分,意味着它经过了大量的测试和调试

我将介绍两个使用flag包的Go程序:一个简单的和一个复杂的。

Expand Down Expand Up @@ -100,114 +101,80 @@ type Value interface {
```go
package main

import (
"flag"
"fmt"
"strings"
import(
"flag"
"fmt"
"strings"
)

type NamesFlag struct {
Names []string
Names []string
}
```

`NamesFlag`结构将用于`flag.Value`接口。
`NamesFlag` 数据结构用于 `flag.Value` 接口。

`funWithFlag.go`第二部分代码如下
`funWithFlag.go` 的第二部分如下

```go
func (s *NamesFlag) GetNames() []string {
return s.Names
func (s *NamesFlag) GetNames() []string{
return s.Names
}

func (s *NamesFlag) String() string {
return fmt.Sprint(s.Names)
return fmt.Sprint(s.Names)
}
```

`funWithFlag.go`第三部分代码如下
`funWithFlag.go` 的第三部分代码如下

```go
func (s *NamesFlag) Set(v string) error {
if len(s.Names) > 0 {
return fmt.Errorf("Cannot use names flag more than once!")
}

names := strings.Split(v, ",")
for _, item := range names {
s.Names = append(s.Names, item)
}

return nil
if len(s.Names) > 0 {
return fmt.Errorf("Cannot use names flag more than once!")
}

names := strings.Split(v, ",")
for _, item := range names {
s.Names = append(s.Names, item)
}
return nil
}
```

首先,`Set()`方法确保相关的命令行选项没有设置。然后,它获取输入,并调用`strings.Split()`函数分割输入参数。分割后的参数保存在`NamesFlag`结构的`Names`字段中
首先,`Set()` 方法确保相关命令行选项没有被设置。之后,获取输入并使用 `strings.Split()` 函数来分隔参数。最后,参数被保存在 `NamesFlag` 结构的 `Names` 字段

`funWithFlag.go`第四部分代码如下:
`funWithFlag.go` 的第四部分代码如下:

```go
func main() {
var manyNames NamesFlag

minusK := flag.Int("k", 0, "An int")
minusO := flag.String("o", "Mihalis", "The name")
flag.Var(&manyNames, "names", "Comma-separated list")

flag.Parse()
fmt.Println("-k:", *minusK)
fmt.Println("-o:", *minusO)
var manyNames NamesFlag
minusK := flag.Int("k:", 0, "An int")
minusO := flag.String("o", "Mihalis", "The name")
flag.Var(&manyNames, "names", "Comma-separated list")

flag.Parse()
fmt.Println("-k:", *minusK)
fmt.Println("-o:", *minusO)
```
`funWithFlag.go`最后一部分代码如下:
`funWithFlag.go` 的最后部分如下:
```go
for i, item := range manyNames.GetNames() {
fmt.Println(i, item)
}

fmt.Println("Remaining command-line arguments:")
for index, val := range flag.Args() {
fmt.Println(index, ":", val)
}
for i, item := range manyNames.GetNames() {
fmt.Println(i, item)
}
fmt.Println("Remaing command-line arugments:")
for index, val := range flag.Args() {
fmt.Println(index, ":", val)
}
}
```

`flag.Args()`切片保留了命令行参数,而变量`manyNames`保存了命令行选项`flag.Var()`的值
`flag.Args()` 切片保留命令行参数,而 `manyNames` 变量保留来自 `flag.Var()` 命令行选项的值

执行`funWithFlag.go`会得到如下的输出
执行 `funWithFlag.go` 产生如下输出

```shell
$ go run funWithFlag.go -names=Mihalis,Jim,Athina 1 two Three
-k: 0
-o: Mihalis
0 Mihalis
1 Jim
2 Athina
Remaining command-line arguments:
0 : 1
1 : two
2 : Three
$ go run funWithFlag.go -Invalid=Marietta 1 two Three
flag provided but not defined: -Invalid
Usage of funWithFlag:
-k int
An int
-names value
Comma-separated list
-o string
The name (default "Mihalis")
exit status 2
$ go run funWithFlag.go -names=Marietta -names=Mihalis
invalid value "Mihalis" for flag -names: Cannot use names flag more than once!
Usage of funWithFlag:
-k int
An int
-names value
Comma-separated list
-o string
The name (default "Mihalis")
exit status 2
```
![""](https://github.com/hantmac/Mastering_Go_ZH_CN/tree/master/images/chapter8/8.2.jpg)

> *除非您开发一个不需要选项的命令行小工具,否则您极需要使用 `flag` 包来处理您的程序的命令行选项。*
除非你正在开发一个不需要命令行选项的简单命令行实用程序,否则你很可能需要使用`flag`包来处理程序的命令行参数。

0 comments on commit 91fa337

Please sign in to comment.