Browse Source

精校:4.8-5.1

Unknwon 3 years ago
parent
commit
ca32f5a4de
5 changed files with 203 additions and 163 deletions
  1. 2 2
      eBook/04.7.md
  2. 37 33
      eBook/04.8.md
  3. 55 43
      eBook/04.9.md
  4. 4 4
      eBook/05.0.md
  5. 105 81
      eBook/05.1.md

+ 2 - 2
eBook/04.7.md

@@ -273,7 +273,7 @@ func main() {
273 273
 	GO1 - The ABC of Go - 25 -
274 274
 	sl2 joined by ;: GO1;The ABC of Go;25
275 275
 
276
-其它有关字符串操作的文档请参阅官方文档 [http://golang.org/pkg/strings/](http://golang.org/pkg/strings/)( **译者注:国内用户可访问 [该页面](http://docs.studygolang.com/pkg/strings/)** )。
276
+其它有关字符串操作的文档请参阅 [官方文档](http://golang.org/pkg/strings/)( **译者注:国内用户可访问 [该页面](http://docs.studygolang.com/pkg/strings/)** )。
277 277
 
278 278
 ## 4.7.11 从字符串中读取内容
279 279
 
@@ -341,7 +341,7 @@ func main() {
341 341
 
342 342
 在第 5.1 节,我们将会利用 if 语句来对可能出现的错误进行分类处理。
343 343
 
344
-更多有关该包的讨论,请参阅官方文档 [http://golang.org/pkg/strconv/](http://golang.org/pkg/strconv/)( **译者注:国内用户可访问 [该页面](http://docs.studygolang.com/pkg/strconv/)** )。
344
+更多有关该包的讨论,请参阅 [官方文档](http://golang.org/pkg/strconv/)( **译者注:国内用户可访问 [该页面](http://docs.studygolang.com/pkg/strconv/)** )。
345 345
 
346 346
 ## 链接
347 347
 

+ 37 - 33
eBook/04.8.md

@@ -9,44 +9,48 @@ Duration 类型表示两个连续时刻所相差的纳秒数,类型为 int64
9 9
 包中的一个预定义函数 `func (t Time) Format(layout string) string` 可以根据一个格式化字符串来将一个时间 t 转换为相应格式的字符串,你可以使用一些预定义的格式,如:`time.ANSIC` 或 `time.RFC822`。 
10 10
 
11 11
 一般的格式化设计是通过对于一个标准时间的格式化描述来展现的,这听起来很奇怪,但看下面这个例子你就会一目了然:
12
-
13
-	fmt.Println(t.Format("02 Jan 2006 15:04")) 
12
+
13
+```go
14
+fmt.Println(t.Format("02 Jan 2006 15:04")) 
15
+```
14 16
 
15 17
 输出:
16 18
 
17 19
 	21 Jul 2011 10:31
18 20
 
19
-其它有关时间操作的文档请参阅官方文档 [http://golang.org/pkg/time/](http://golang.org/pkg/time/)( **译者注:国内用户可访问 [http://docs.studygolang.com/pkg/time/](http://docs.studygolang.com/pkg/time/)** )。
20
-
21
-Example 4.20 [time.go](examples/chapter_4/time.go)
22
-
23
-	package main
24
-	import (
25
-		"fmt"
26
-		"time"
27
-	)
28
-
29
-	var week time.Duration
30
-	func main() {
31
-		t := time.Now()
32
-		fmt.Println(t) // e.g. Wed Dec 21 09:52:14 +0100 RST 2011
33
-		fmt.Printf("%02d.%02d.%4d\n", t.Day(), t.Month(), t.Year())
34
-		// 21.12.2011
35
-		t = time.Now().UTC()
36
-		fmt.Println(t) // Wed Dec 21 08:52:14 +0000 UTC 2011
37
-		fmt.Println(time.Now()) // Wed Dec 21 09:52:14 +0100 RST 2011
38
-		// calculating times:
39
-		week = 60 * 60 * 24 * 7 * 1e9 // must be in nanosec
40
-		week_from_now := t.Add(week)
41
-		fmt.Println(week_from_now) // Wed Dec 28 08:52:14 +0000 UTC 2011
42
-		// formatting times:
43
-		fmt.Println(t.Format(time.RFC822)) // 21 Dec 11 0852 UTC
44
-		fmt.Println(t.Format(time.ANSIC)) // Wed Dec 21 08:56:34 2011
45
-		fmt.Println(t.Format("02 Jan 2006 15:04")) // 21 Dec 2011 08:52
46
-		s := t.Format("20060102")
47
-		fmt.Println(t, "=>", s)
48
-		// Wed Dec 21 08:52:14 +0000 UTC 2011 => 20111221
49
-	}
21
+其它有关时间操作的文档请参阅 [官方文档](http://golang.org/pkg/time/)( **译者注:国内用户可访问 [该页面](http://docs.studygolang.com/pkg/time/)** )。
22
+
23
+示例 4.20 [time.go](examples/chapter_4/time.go)
24
+
25
+```go
26
+package main
27
+import (
28
+	"fmt"
29
+	"time"
30
+)
31
+
32
+var week time.Duration
33
+func main() {
34
+	t := time.Now()
35
+	fmt.Println(t) // e.g. Wed Dec 21 09:52:14 +0100 RST 2011
36
+	fmt.Printf("%02d.%02d.%4d\n", t.Day(), t.Month(), t.Year())
37
+	// 21.12.2011
38
+	t = time.Now().UTC()
39
+	fmt.Println(t) // Wed Dec 21 08:52:14 +0000 UTC 2011
40
+	fmt.Println(time.Now()) // Wed Dec 21 09:52:14 +0100 RST 2011
41
+	// calculating times:
42
+	week = 60 * 60 * 24 * 7 * 1e9 // must be in nanosec
43
+	week_from_now := t.Add(week)
44
+	fmt.Println(week_from_now) // Wed Dec 28 08:52:14 +0000 UTC 2011
45
+	// formatting times:
46
+	fmt.Println(t.Format(time.RFC822)) // 21 Dec 11 0852 UTC
47
+	fmt.Println(t.Format(time.ANSIC)) // Wed Dec 21 08:56:34 2011
48
+	fmt.Println(t.Format("02 Jan 2006 15:04")) // 21 Dec 2011 08:52
49
+	s := t.Format("20060102")
50
+	fmt.Println(t, "=>", s)
51
+	// Wed Dec 21 08:52:14 +0000 UTC 2011 => 20111221
52
+}
53
+```
50 54
 
51 55
 输出的结果已经写在每行 `//` 的后面。
52 56
 

+ 55 - 43
eBook/04.9.md

@@ -8,14 +8,18 @@
8 8
 
9 9
 Go 语言的取地址符是 `&`,放到一个变量前使用就会返回相应变量的内存地址。
10 10
 
11
-下面的代码片段(Example 4.9 [pointer.go](examples/chapter_4/pointer.go))可能输出 `An integer: 5, its location in memory: 0x6b0820`(这个值随着你每次运行程序而变化)。
12
-
13
-	var i1 = 5
14
-	fmt.Printf("An integer: %d, it's location in memory: %p\n", i1, &i1)
11
+下面的代码片段(示例 4.9 [pointer.go](examples/chapter_4/pointer.go))可能输出 `An integer: 5, its location in memory: 0x6b0820`(这个值随着你每次运行程序而变化)。
12
+
13
+```go
14
+var i1 = 5
15
+fmt.Printf("An integer: %d, it's location in memory: %p\n", i1, &i1)
16
+```
15 17
 
16 18
 这个地址可以存储在一个叫做指针的特殊数据类型中,在本例中这是一个指向 int 的指针,即 `i1`:此处使用 *int 表示。如果我们想调用指针 intP,我们可以这样声明它:
17
-
18
-	var intP *int
19
+
20
+```go
21
+var intP *int
22
+```
19 23
 
20 24
 然后使用 `intP = &i1` 是合法的,此时 intP 指向 i1。
21 25
 
@@ -39,20 +43,22 @@ intP 存储了 i1 的内存地址;它指向了 i1 的位置,它引用了变
39 43
 
40 44
 现在,我们应当能理解 pointer.go 中的整个程序和他的输出:
41 45
 
42
-Example 4.21 [pointer.go](examples/chapter_4/pointer.go):
43
-
44
-	package main
45
-	import "fmt"
46
-	func main() {
47
-		var i1 = 5
48
-		fmt.Printf("An integer: %d, its location in memory: %p\n", i1, &i1)
49
-		var intP *int
50
-		intP = &i1
51
-		fmt.Printf("The value at memory location %p is %d\n", intP, *intP)
52
-	}
46
+示例 4.21 [pointer.go](examples/chapter_4/pointer.go):
47
+
48
+```go
49
+package main
50
+import "fmt"
51
+func main() {
52
+	var i1 = 5
53
+	fmt.Printf("An integer: %d, its location in memory: %p\n", i1, &i1)
54
+	var intP *int
55
+	intP = &i1
56
+	fmt.Printf("The value at memory location %p is %d\n", intP, *intP)
57
+}
58
+```
53 59
 
54 60
 输出:
55
- 
61
+
56 62
 	An integer: 5, its location in memory: 0x24f0820
57 63
 	The value at memory location 0x24f0820 is 5
58 64
 
@@ -64,18 +70,20 @@ Example 4.21 [pointer.go](examples/chapter_4/pointer.go):
64 70
 
65 71
 它展示了分配一个新的值给 *p 并且更改这个变量自己的值(这里是一个字符串)。
66 72
 
67
-Example 4.22 [string_pointer.go](examples/chapter_4/string_pointer.go)
68
-
69
-	package main
70
-	import "fmt"
71
-	func main() {
72
-		s := "good bye"
73
-		var p *string = &s
74
-		*p = "ciao"
75
-		fmt.Printf("Here is the pointer p: %p\n", p) // prints address
76
-		fmt.Printf("Here is the string *p: %s\n", *p) // prints string
77
-		fmt.Printf("Here is the string s: %s\n", s) // prints same string
78
-	}
73
+示例 4.22 [string_pointer.go](examples/chapter_4/string_pointer.go)
74
+
75
+```go
76
+package main
77
+import "fmt"
78
+func main() {
79
+	s := "good bye"
80
+	var p *string = &s
81
+	*p = "ciao"
82
+	fmt.Printf("Here is the pointer p: %p\n", p) // prints address
83
+	fmt.Printf("Here is the string *p: %s\n", *p) // prints string
84
+	fmt.Printf("Here is the string s: %s\n", s) // prints same string
85
+}
86
+```
79 87
 
80 88
 输出:
81 89
 
@@ -92,10 +100,12 @@ Example 4.22 [string_pointer.go](examples/chapter_4/string_pointer.go)
92 100
 **注意事项** 
93 101
 
94 102
 你不能得到一个文字或常量的地址,例如:
95
-
96
-	const i = 5
97
-	ptr := &i //error: cannot take the address of i
98
-	ptr2 := &10 //error: cannot take the address of 10
103
+
104
+```go
105
+const i = 5
106
+ptr := &i //error: cannot take the address of i
107
+ptr2 := &10 //error: cannot take the address of 10
108
+```
99 109
 
100 110
 所以说,Go 语言和 C、C++ 以及 D 语言这些低级(系统)语言一样,都有指针的概念。但是对于经常导致 C 语言内存泄漏继而程序崩溃的指针运算(所谓的指针算法,如:`pointer+2`,移动指针指向字符串的字节数或数组的某个位置)是不被允许的。Go 语言中的指针保证了内存安全,更像是 Java、C# 和 VB.NET 中的引用。
101 111
 
@@ -111,15 +121,17 @@ Example 4.22 [string_pointer.go](examples/chapter_4/string_pointer.go)
111 121
 
112 122
 对一个空指针的反向引用是不合法的,并且会使程序崩溃:
113 123
 
114
-Example 4.23 [testcrash.go](examples/chapter_4/testcrash.go):
115
-
116
-	package main
117
-	func main() {
118
-		var p *int = nil
119
-		*p = 0
120
-	}
121
-	// in Windows: stops only with: <exit code="-1073741819" msg="process crashed"/>
122
-	// runtime error: invalid memory address or nil pointer dereference
124
+示例 4.23 [testcrash.go](examples/chapter_4/testcrash.go):
125
+
126
+```go
127
+package main
128
+func main() {
129
+	var p *int = nil
130
+	*p = 0
131
+}
132
+// in Windows: stops only with: <exit code="-1073741819" msg="process crashed"/>
133
+// runtime error: invalid memory address or nil pointer dereference
134
+```
123 135
 
124 136
 **问题 4.2** 列举 Go 语言中 * 号的所有用法。
125 137
 

+ 4 - 4
eBook/05.0.md

@@ -2,13 +2,13 @@
2 2
 
3 3
 到目前为止,我们看到的都是 Go 程序都是从 main() 函数开始执行,然后按顺序执行该函数体中的代码。但我们经常会需要只有在满足一些特定情况时才执行某些代码,也就是说在代码里进行条件判断。针对这种需求,Go 提供了下面这些条件结构和分支结构:
4 4
 
5
-	if-else 结构
6
-	switch 结构
7
-	select 结构,用于 channel 的选择(第 14.4 节)
5
+- if-else 结构
6
+- switch 结构
7
+- elect 结构,用于 channel 的选择(第 14.4 节)
8 8
 
9 9
 可以使用迭代或循环结构来重复执行一次或多次某段代码(任务):
10 10
 
11
-	for (range) 结构
11
+- for (range) 结构
12 12
 
13 13
 一些如 `break` 和 `continue` 这样的关键字可以用于中途改变循环的状态。
14 14
 

+ 105 - 81
eBook/05.1.md

@@ -2,27 +2,33 @@
2 2
 
3 3
 if 是用于测试某个条件(布尔型或逻辑型)的语句,如果该条件成立,则会执行 if 后由大括号括起来的代码块,否则就忽略该代码块继续执行后续的代码。
4 4
 
5
-	if condition {
6
-		// do something	
7
-	}
5
+```go
6
+if condition {
7
+	// do something	
8
+}
9
+```
8 10
 
9 11
 如果存在第二个分支,则可以在上面代码的基础上添加 else 关键字以及另一代码块,这个代码块中的代码只有在条件不满足时才会执行。if 和 else 后的两个代码块是相互独立的分支,只可能执行其中一个。
10 12
 
11
-	if condition {
12
-		// do something	
13
-	} else {
14
-		// do something	
15
-	}
13
+```go
14
+if condition {
15
+	// do something	
16
+} else {
17
+	// do something	
18
+}
19
+```
16 20
 
17 21
 如果存在第三个分支,则可以使用下面这种三个独立分支的形式:
18 22
 
19
-	if condition1 {
20
-		// do something	
21
-	} else if condition2 {
22
-		// do something else	
23
-	}else {
24
-		// catch-all or default
25
-	}
23
+```go
24
+if condition1 {
25
+	// do something	
26
+} else if condition2 {
27
+	// do something else	
28
+}else {
29
+	// catch-all or default
30
+}
31
+```
26 32
 
27 33
 else-if 分支的数量是没有限制的,但是为了代码的可读性,还是不要在 if 后面加入太多的 else-if 结构。如果你必须使用这种形式,则把尽可能先满足的条件放在前面。
28 34
 
@@ -32,10 +38,12 @@ else-if 分支的数量是没有限制的,但是为了代码的可读性,还
32 38
 
33 39
 非法的Go代码:
34 40
 
35
-	if x{
36
-	}
37
-	else {	// 无效的
38
-	}
41
+```go
42
+if x{
43
+}
44
+else {	// 无效的
45
+}
46
+```
39 47
 
40 48
 要注意的是,在你使用 `gofmt` 格式化代码之后,每个分支内的代码都会缩进 4 个或 8 个空格,或者是 1 个 tab,并且右大括号与对应的 if 关键字垂直对齐。
41 49
 
@@ -43,18 +51,20 @@ else-if 分支的数量是没有限制的,但是为了代码的可读性,还
43 51
 
44 52
 一种可能用到条件语句的场景是测试变量的值,在不同的情况执行不同的语句,不过将在第 5.3 节讲到的 switch 结构会更适合这种情况。
45 53
 
46
-Example 5.1 [booleans.go](examples/chapter_5/booleans.go)
54
+示例 5.1 [booleans.go](examples/chapter_5/booleans.go)
47 55
 
48
-	package main
49
-	import "fmt"
50
-	func main() {
51
-		bool1 := true
52
-		if bool1 {
53
-			fmt.Printf("The value is true\n")
54
-		} else {
55
-			fmt.Printf("The value is false\n")
56
-		}
56
+```go
57
+package main
58
+import "fmt"
59
+func main() {
60
+	bool1 := true
61
+	if bool1 {
62
+		fmt.Printf("The value is true\n")
63
+	} else {
64
+		fmt.Printf("The value is false\n")
57 65
 	}
66
+}
67
+```
58 68
 
59 69
 输出:
60 70
 	
@@ -66,22 +76,26 @@ Example 5.1 [booleans.go](examples/chapter_5/booleans.go)
66 76
 
67 77
 当 if 结构内有 break、continue、goto 或者 return 语句时,Go 代码的常见写法是省略 else 部分(另见第 5.2 节)。无论满足哪个条件都会返回 x 或者 y 时,一般使用以下写法:
68 78
 
69
-	if condition {
70
-		return x
71
-	}
72
-	return y
79
+```go
80
+if condition {
81
+	return x
82
+}
83
+return y
84
+```
73 85
 
74
-**注意事项** 不要同时在 if-else 结构的两个分支里都使用 return 语句,这将导致编译报错 “function ends without a return statement”(你可以认为这是一个编译器的 Bug 或者特性)。( **译者注:该问题已经在 Go 1.1 中被修复或者说改进** )
86
+**注意事项** 不要同时在 if-else 结构的两个分支里都使用 return 语句,这将导致编译报错 `function ends without a return statement`(你可以认为这是一个编译器的 Bug 或者特性)。( **译者注:该问题已经在 Go 1.1 中被修复或者说改进** )
75 87
 
76 88
 这里举一些有用的例子:
77 89
 
78
-1. 判断一个字符串是否为空:`if str == "" { ... }` 或 `if len(str) == 0 {...}`。
90
+1. 判断一个字符串是否为空:
91
+	- `if str == "" { ... }`
92
+	- `if len(str) == 0 {...}`	
79 93
 2. 判断运行 Go 程序的操作系统类型,这可以通过常量 `runtime.GOOS` 来判断(第 2.2 节)。
80
-
81
-		if runtime.GOOS == "windows" {
82
-			...
83
-		} else { // Unix - like
84
-			...
94
+	
95
+		if runtime.GOOS == "windows"	 {
96
+			.	..
97
+		} else { // Unix - li	ke
98
+			.	..
85 99
 		}
86 100
 
87 101
 	这段代码一般被放在 init() 函数中执行。这儿还有一段示例来演示如何根据操作系统来决定输入结束的提示:
@@ -116,53 +130,61 @@ Example 5.1 [booleans.go](examples/chapter_5/booleans.go)
116 130
 
117 131
 在第四种情况中,if 可以包含一个初始化语句(如:给一个变量赋值)。这种写法具有固定的格式(在初始化语句后方必须加上分号):
118 132
 
119
-	if initialization; condition {
120
-		// do something
121
-	}
133
+```go
134
+if initialization; condition {
135
+	// do something
136
+}
137
+```
122 138
 
123 139
 例如:
124 140
 
125
-	val := 10
126
-	if val > max {
127
-		// do something
128
-	}
141
+```go
142
+val := 10
143
+if val > max {
144
+	// do something
145
+}
146
+```
129 147
 
130 148
 你也可以这样写:
131 149
 
132
-	if val := 10; val > max {
133
-		// do something
134
-	}
150
+```go
151
+if val := 10; val > max {
152
+	// do something
153
+}
154
+```
135 155
 
136 156
 但要注意的是,使用简短方式 `:=` 声明的变量的作用域只存在于 if 结构中(在 if 结构的大括号之间,如果使用 if-else 结构则在 else 代码块中变量也会存在)。如果变量在 if 结构之前就已经存在,那么在 if 结构中,该变量原来的值会被隐藏。最简单的解决方案就是不要在初始化语句中声明变量(见 5.2 节的例 3 了解更多)。
137 157
 
138
-Example 5.2 [ifelse.go](examples/chapter_5/ifelse.go)
158
+示例 5.2 [ifelse.go](examples/chapter_5/ifelse.go)
139 159
 
140
-	package main
141
-	
142
-	import "fmt"
143
-	
144
-	func main() {
145
-		var first int = 10
146
-		var cond int
147
-	
148
-		if first <= 0 {
149
-	
150
-			fmt.Printf("first is less than or equal to 0\n")
151
-		} else if first > 0 && first < 5 {
152
-	
153
-			fmt.Printf("first is between 0 and 5\n")
154
-		} else {
155
-	
156
-			fmt.Printf("first is 5 or greater\n")
157
-		}
158
-		if cond = 5; cond > 10 {
159
-	
160
-			fmt.Printf("cond is greater than 10\n")
161
-		} else {
162
-	
163
-			fmt.Printf("cond is not greater than 10\n")
164
-		}
160
+```go
161
+package main
162
+
163
+import "fmt"
164
+
165
+func main() {
166
+	var first int = 10
167
+	var cond int
168
+
169
+	if first <= 0 {
170
+
171
+		fmt.Printf("first is less than or equal to 0\n")
172
+	} else if first > 0 && first < 5 {
173
+
174
+		fmt.Printf("first is between 0 and 5\n")
175
+	} else {
176
+
177
+		fmt.Printf("first is 5 or greater\n")
165 178
 	}
179
+	if cond = 5; cond > 10 {
180
+
181
+		fmt.Printf("cond is greater than 10\n")
182
+	} else {
183
+
184
+		fmt.Printf("cond is not greater than 10\n")
185
+	}
186
+}
187
+```
166 188
 
167 189
 输出:
168 190
 
@@ -170,11 +192,13 @@ Example 5.2 [ifelse.go](examples/chapter_5/ifelse.go)
170 192
 
171 193
 下面的代码片段展示了如何通过在初始化语句中获取函数 `process()` 的返回值,并在条件语句中作为判定条件来决定是否执行 if 结构中的代码:
172 194
 
173
-	if value := process(data); value > max {
174
-		...
175
-	if value := process(data); value > max {
176
-		...
177
-	}
195
+```go
196
+if value := process(data); value > max {
197
+	...
198
+if value := process(data); value > max {
199
+	...
200
+}
201
+```
178 202
 
179 203
 ## 链接
180 204