Przeglądaj źródła

Merge pull request #132 from kuuyee/master

提交12.3和12.4两章的翻译
无闻 10 lat temu
rodzic
commit
4be16b7ab0
2 zmienionych plików z 176 dodań i 0 usunięć
  1. 44 0
      eBook/12.3.md
  2. 132 0
      eBook/12.4.md

+ 44 - 0
eBook/12.3.md

@@ -0,0 +1,44 @@
+# 文件拷贝
+如何拷贝一个文件到另一个文件?最简单的方式就是使用io包:
+
+示例 12.10 [filecopy.go](examples/chapter_12/filecopy.go):
+```go
+// filecopy.go
+package main
+
+import (
+	"fmt"
+	"io"
+	"os"
+)
+
+func main() {
+	CopyFile("target.txt", "source.txt")
+	fmt.Println("Copy done!")
+}
+
+func CopyFile(dstName, srcName string) (written int64, err error) {
+	src, err := os.Open(srcName)
+	if err != nil {
+		return
+	}
+	defer src.Close()
+
+	dst, err := os.OpenFile(dstName, os.O_WRONLY|os.O_CREATE, 0644)
+	if err != nil {
+		return
+	}
+	defer dst.Close()
+
+	return io.Copy(dst, src)
+}
+
+```
+
+注意要使用`defer`:当打开目标文件时发生了错误,那么`defer`仍然能够确保`src.Close()`执行。如果不这么做,那么文件会一直保持打开状态并占用资源。
+
+## 链接
+
+- [目录](directory.md)
+- 上一节:[文件读写](12.2.md)
+- 下一节:[从命令行读取参数](12.4.md)

+ 132 - 0
eBook/12.4.md

@@ -0,0 +1,132 @@
+# 从命令行读取参数
+## 12.4.1 os包
+os包中有一个string类型的切片变量`os.Args`,其用来处理一些基本的命令行参数,它在程序启动后读取命令行输入的参数。来看下面的打招呼程序:
+
+示例 12.11 [os_args.go](examples/chapter_12/os_args.go):
+```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](exercises/chapter_12/hello_who.go)
+写一个"Hello World"的变种程序:把人的名字作为程序命令行执行的一个参数,比如: `hello_who Evan Michael Laura` 那么会输出`Hello Evan Michael Laura`!
+
+## 12.4.2 flag包
+flag包有一个扩展功能用来解析命令行选项。但是通常被用来替换基本常量,例如,在某些情况下我们希望在命令行给常量一些不一样的值。(参看19章的项目)
+
+在flag包中一个Flag被定义成一个含有如下字段的结构体:
+
+```go
+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功能:
+
+```go
+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的使用帮助信息,本例中打印的是:
+
+```go
+	-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`,将输出:
+
+```go
+A
+B
+C
+```
+
+每个字符的输出都新起一行,每次都在输出的数据前面打印使用帮助信息:`-n=false: print newline`
+
+对于`flag.Bool`你可以设置布尔型flag来测试你的代码,例如定义一个flag `processedFlag`:
+
+```go
+	var processedFlag = flag.Bool(“proc”, false, “nothing processed yet”)
+```
+
+在后面用如下代码来测试:
+
+```go
+	if *processedFlag { // found flag -proc
+		r = process()
+	}
+```
+
+要给flag定义其它类型,可以使用`flag.Int()`,`flag.Float64`,`flag.String()`
+
+在15.8章你将找到一个完成的例子。
+
+
+
+## 链接
+
+- [目录](directory.md)
+- 上一节:[文件拷贝](12.3.md)
+- 下一节:[用buffer读取文件](12.5.md)
+
+