Skip to content

Commit d2bc9ae

Browse files
committed
update 11-21
1 parent a6501fd commit d2bc9ae

File tree

18 files changed

+87
-107
lines changed

18 files changed

+87
-107
lines changed

PROGRESS.md

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -18,17 +18,17 @@
1818
- [x] Arrays->数组
1919
- [x] Slices->切片
2020
- [x] Maps->Map
21-
- [ ] Range->Range 遍历
22-
- [ ] Functions->函数
23-
- [ ] Multiple Return Values->多返回值
24-
- [ ] Variadic Functions->变参函数
25-
- [ ] Closures->闭包
26-
- [ ] Recursion->递归
27-
- [ ] Pointers->指针
28-
- [ ] Structs->结构体
29-
- [ ] Methods->方法
30-
- [ ] Interfaces->接口
31-
- [ ] Errors->错误处理
21+
- [x] Range->Range 遍历
22+
- [x] Functions->函数
23+
- [x] Multiple Return Values->多返回值
24+
- [x] Variadic Functions->变参函数
25+
- [x] Closures->闭包
26+
- [x] Recursion->递归
27+
- [x] Pointers->指针
28+
- [x] Structs->结构体
29+
- [x] Methods->方法
30+
- [x] Interfaces->接口
31+
- [x] Errors->错误处理
3232
- [ ] Goroutines->协程
3333
- [ ] Channels->通道
3434
- [ ] Channel Buffering->通道缓冲

examples/closures/closures.go

Lines changed: 8 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,13 @@
1-
// Go 支持[_匿名函数_](http://zh.wikipedia.org/wiki/%E5%8C%BF%E5%90%8D%E5%87%BD%E6%95%B0),并能用其构造 <a href="http://zh.wikipedia.org/wiki/%E9%97%AD%E5%8C%85_(%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%A7%91%E5%AD%A6)"><em>闭包</em></a>。
1+
// Go 支持[_匿名函数_](http://zh.wikipedia.org/wiki/%E5%8C%BF%E5%90%8D%E5%87%BD%E6%95%B0),
2+
// 并能用其构造 <a href="http://zh.wikipedia.org/wiki/%E9%97%AD%E5%8C%85_(%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%A7%91%E5%AD%A6)"><em>闭包</em></a>。
23
// 匿名函数在你想定义一个不需要命名的内联函数时是很实用的。
3-
44
package main
55

66
import "fmt"
77

8-
// 这个 `intSeq` 函数返回另一个在 `intSeq` 函数体内定义的
9-
// 匿名函数。这个返回的函数使用闭包的方式 _隐藏_ 变量 `i`。
8+
// `intSeq` 函数返回一个在其函数体内定义的匿名函数。
9+
// 返回的函数使用闭包的方式 _隐藏_ 变量 `i`。
10+
// 返回的函数 _隐藏_ 变量 `i` 以形成闭包。
1011
func intSeq() func() int {
1112
i := 0
1213
return func() int {
@@ -17,18 +18,16 @@ func intSeq() func() int {
1718

1819
func main() {
1920

20-
// 我们调用 `intSeq` 函数,将返回值(一个函数)赋给
21-
// `nextInt`。这个函数的值包含了自己的值 `i`,这样在每
22-
// 次调用 `nextInt` 时都会更新 `i` 的值。
21+
// 我们调用 `intSeq` 函数,将返回值(一个函数)赋给 `nextInt`。
22+
// 这个函数的值包含了自己的值 `i`,这样在每次调用 `nextInt` 时,都会更新 `i` 的值。
2323
nextInt := intSeq()
2424

2525
// 通过多次调用 `nextInt` 来看看闭包的效果。
2626
fmt.Println(nextInt())
2727
fmt.Println(nextInt())
2828
fmt.Println(nextInt())
2929

30-
// 为了确认这个状态对于这个特定的函数是唯一的,我们
31-
// 重新创建并测试一下。
30+
// 为了确认这个状态对于这个特定的函数是唯一的,我们重新创建并测试一下。
3231
newInts := intSeq()
3332
fmt.Println(newInts())
3433
}

examples/errors/errors.go

Lines changed: 12 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,18 @@
11
// 符合 Go 语言习惯的做法是使用一个独立、明确的返回值来传递错误信息。
2-
// 这与使用异常(exception)的 Java 和 Ruby
3-
// 以及在 C 语言中有时用到的重载(overloaded)的单返回/错误值有着明显的不同。
4-
// Go 语言的处理方式能清楚的知道哪个函数
5-
// 返回了错误,并能像调用那些没有出错的函数一样调用。
2+
// 这与 Java、Ruby 使用的异常(exception)
3+
// 以及在 C 语言中有时用到的重载 (overloaded) 的单返回/错误值有着明显的不同。
4+
// Go 语言的处理方式能清楚的知道哪个函数返回了错误,并使用跟其他(无异常处理的)语言类似的方式来处理错误。
65

76
package main
87

98
import "errors"
109
import "fmt"
1110

12-
// 按照惯例,错误通常是最后一个返回值并且是 `error` 类
13-
// 型,一个内建的接口。
11+
// 按照惯例,错误通常是最后一个返回值并且是 `error` 类型,它是一个内建的接口。
1412
func f1(arg int) (int, error) {
1513
if arg == 42 {
1614

17-
// `errors.New` 构造一个使用给定的错误信息的基本
18-
// `error` 值。
15+
// `errors.New` 使用给定的错误信息构造一个基本的 `error` 值。
1916
return -1, errors.New("can't work with 42")
2017

2118
}
@@ -24,7 +21,7 @@ func f1(arg int) (int, error) {
2421
return arg + 3, nil
2522
}
2623

27-
// 通过实现 `Error` 方法来自定义 `error` 类型是可以的
24+
// 你还可以通过实现 `Error()` 方法来自定义 `error` 类型
2825
// 这里使用自定义错误类型来表示上面例子中的参数错误。
2926
type argError struct {
3027
arg int
@@ -38,18 +35,17 @@ func (e *argError) Error() string {
3835
func f2(arg int) (int, error) {
3936
if arg == 42 {
4037

41-
// 在这个例子中,我们使用 `&argError` 语法来建立一个
42-
// 新的结构体,并提供了 `arg` 和 `prob` 这两个字段
43-
// 的值。
38+
// 在这个例子中,我们使用 `&argError` 语法来建立一个新的结构体,
39+
// 并提供了 `arg` 和 `prob` 两个字段的值。
4440
return -1, &argError{arg, "can't work with it"}
4541
}
4642
return arg + 3, nil
4743
}
4844

4945
func main() {
5046

51-
// 下面的两个循环测试了各个返回错误的函数。注意在 `if`
52-
// 行内的错误检查代码,在 Go 中是一个普遍的用法
47+
// 下面的两个循环测试了每一个会返回错误的函数。
48+
// 注意,在 `if` 的同一行进行错误检查,是 Go 代码中的一种常见用法
5349
for _, i := range []int{7, 42} {
5450
if r, e := f1(i); e != nil {
5551
fmt.Println("f1 failed:", e)
@@ -65,8 +61,8 @@ func main() {
6561
}
6662
}
6763

68-
// 你如果想在程序中使用一个自定义错误类型中的数据,你
69-
// 需要通过类型断言来得到这个错误类型的实例
64+
// 如果你想在程序中使用自定义错误类型的数据,
65+
// 你需要通过类型断言来得到这个自定义错误类型的实例
7066
_, e := f2(42)
7167
if ae, ok := e.(*argError); ok {
7268
fmt.Println(ae.arg)

examples/errors/errors.sh

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,5 +6,5 @@ f2 failed: 42 - can't work with it
66
42
77
can't work with it
88
9-
# 到 Go 官方博客去看这篇[很棒的文章](http://blog.golang.org/2011/07/error-handling-and-go.html)
10-
# 获取更多关于错误处理的信息
9+
# 到 Go 官方博客去看这篇[很棒的文章](http://blog.golang.org/2011/07/error-handling-and-go.html)
10+
# 以获取更多关于错误处理的信息

examples/functions/functions.go

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,27 +1,25 @@
1-
// _函数_ 是 Go 的中心。我们将通过一些不同的例子来
2-
// 进行学习。
3-
1+
// _函数_ 是 Go 的核心。
2+
// 我们将通过一些不同的例子来进行学习。
43
package main
54

65
import "fmt"
76

87
// 这里是一个函数,接受两个 `int` 并且以 `int` 返回它们的和
98
func plus(a int, b int) int {
109

11-
// Go 需要明确的返回,不会自动返回最
12-
// 后一个表达式的值
10+
// Go 需要明确的 return,也就是说,它不会自动 return 最后一个表达式的值
1311
return a + b
1412
}
1513

16-
// 当多个连续的参数为同样类型时,最多可以仅声明最后一个参数类型
17-
// 而忽略之前相同类型参数的类型声明
14+
// 当多个连续的参数为同样类型时,
15+
// 可以仅声明最后一个参数的类型,忽略之前相同类型参数的类型声明
1816
func plusPlus(a, b, c int) int {
1917
return a + b + c
2018
}
2119

2220
func main() {
2321

24-
// 通过 `name(args)` 来调用函数,
22+
// 通过 `函数名(参数列表)` 来调用函数,
2523
res := plus(1, 2)
2624
fmt.Println("1+2 =", res)
2725

examples/functions/functions.sh

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,5 +2,5 @@ $ go run functions.go
22
1+2 = 3
33
1+2+3 = 6
44

5-
# Go 函数有很多其他的特性。其中一个就是多值返回,也是
6-
# 我们接下来需要接触的
5+
# Go 函数还有很多其他的特性。
6+
# 其中一个就是多值返回,它也是我们接下来要接触的

examples/interfaces/interfaces.go

Lines changed: 9 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,27 +1,25 @@
1-
// _接口(Interfaces)_ 是命名了的方法签名(signatures)的集合。
2-
1+
// 方法签名的集合叫做:_接口(Interfaces)_。
32
package main
43

54
import "fmt"
65
import "math"
76

8-
// 这里是一个几何体的基本接口
7+
// 这是一个几何体的基本接口
98
type geometry interface {
109
area() float64
1110
perim() float64
1211
}
1312

14-
// 在我们的例子中,我们将在类型 `rect` 和 `circle` 上实现
15-
// 这个接口
13+
// 在这个例子中,我们将为 `rect` 和 `circle` 实现该接口。
1614
type rect struct {
1715
width, height float64
1816
}
1917
type circle struct {
2018
radius float64
2119
}
2220

23-
// 要在 Go 中实现一个接口,我们就需要实现接口中的所有
24-
// 方法。这里我们在 `rect` 上实现了 `geometry` 接口。
21+
// 要在 Go 中实现一个接口,我们只需要实现接口中的所有方法。
22+
// 这里我们为 `rect` 实现了 `geometry` 接口。
2523
func (r rect) area() float64 {
2624
return r.width * r.height
2725
}
@@ -37,9 +35,8 @@ func (c circle) perim() float64 {
3735
return 2 * math.Pi * c.radius
3836
}
3937

40-
// 如果一个变量具有接口类型,那么我们可以调用指定接口中的
41-
// 方法。这里有一个通用的 `measure` 函数,利用它来在任
42-
// 何的 `geometry` 上工作。
38+
// 如果一个变量实现了某个接口,我们就可以调用指定接口中的方法。
39+
// 这儿有一个通用的 `measure` 函数,我们可以通过它来使用所有的 `geometry`。
4340
func measure(g geometry) {
4441
fmt.Println(g)
4542
fmt.Println(g.area())
@@ -50,8 +47,8 @@ func main() {
5047
r := rect{width: 3, height: 4}
5148
c := circle{radius: 5}
5249

53-
// 结构体类型 `circle` 和 `rect` 都实现了 `geometry`
54-
// 接口,所以我们可以使用它们的实例作为 `measure` 的参数。
50+
// 结构体类型 `circle` 和 `rect` 都实现了 `geometry` 接口,
51+
// 所以我们可以将其实例作为 `measure` 的参数。
5552
measure(r)
5653
measure(c)
5754
}

examples/interfaces/interfaces.sh

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,5 +6,5 @@ $ go run interfaces.go
66
78.53981633974483
77
31.41592653589793
88

9-
# 要学习更多关于 Go 的接口的知识,看看这篇
10-
# [很棒的博文](http://jordanorelli.tumblr.com/post/32665860244/how-to-use-interfaces-in-go)。
9+
# 要学习更多关于 Go 接口的知识,
10+
# 可以看看这篇[很棒的博文](http://jordanorelli.tumblr.com/post/32665860244/how-to-use-interfaces-in-go)。

examples/methods/methods.go

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
1-
// Go 支持在结构体类型中定义_方法(methods)_ 。
2-
1+
// Go 支持为结构体类型定义_方法(methods)_ 。
32
package main
43

54
import "fmt"
@@ -8,13 +7,13 @@ type rect struct {
87
width, height int
98
}
109

11-
// 这里的 `area` 方法有一个_接收器(receiver)类型_ `rect`。
10+
// 这里的 `area` 方法有一个 _接收者类型_:`rect`。
1211
func (r *rect) area() int {
1312
return r.width * r.height
1413
}
1514

16-
// 可以为值类型或者指针类型的接收器定义方法。这里是一个
17-
// 值类型接收器的例子
15+
// 可以为值类型或者指针类型的接收者定义方法。
16+
// 这是一个值类型接收者的例子
1817
func (r rect) perim() int {
1918
return 2*r.width + 2*r.height
2019
}
@@ -26,9 +25,10 @@ func main() {
2625
fmt.Println("area: ", r.area())
2726
fmt.Println("perim:", r.perim())
2827

29-
// Go 自动处理方法调用时的值和指针之间的转化。你可以使
30-
// 用指针来调用方法来避免在方法调用时产生一个拷贝,或者
31-
// 让方法能够改变接受的结构体。
28+
// 调用方法时,Go 会自动处理值和指针之间的转换。
29+
// 想要避免在调用方法时产生一个拷贝,或者想让方法可以修改接受结构体的值,
30+
// 你都可以使用指针来调用方法。
31+
3232
rp := &r
3333
fmt.Println("area: ", rp.area())
3434
fmt.Println("perim:", rp.perim())

examples/methods/methods.sh

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,5 +4,4 @@ perim: 30
44
area: 50
55
perim: 30
66

7-
# 接下来我们将介绍Go用于分组和命名相关
8-
# 方法集合的另一机制:接口。
7+
# 接下来,我们将学习 Go 对方法集进行命名和分组的另一机制:接口。
Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
1-
// Go 内建_多返回值_支持。这个特性在 Go 语言中经常被用到,
2-
// 例如用来同时返回一个函数的结果和错误信息。
3-
1+
// Go 原生支持 _多返回值_。
2+
// 这个特性在 Go 语言中经常用到,例如用来同时返回一个函数的结果和错误信息。
43
package main
54

65
import "fmt"
@@ -12,12 +11,12 @@ func vals() (int, int) {
1211

1312
func main() {
1413

15-
// 这里我们通过_多赋值_操作来使用这两个不同的返回值
14+
// 这里我们通过 _多赋值_ 操作来使用这两个不同的返回值
1615
a, b := vals()
1716
fmt.Println(a)
1817
fmt.Println(b)
1918

20-
// 如果你仅仅需要返回值的一部分的话,你可以使用空白标识符`_`。
19+
// 如果你仅仅需要返回值的一部分的话,你可以使用空白标识符 `_`。
2120
_, c := vals()
2221
fmt.Println(c)
2322
}

examples/multiple-return-values/multiple-return-values.sh

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,5 +3,4 @@ $ go run multiple-return-values.go
33
7
44
7
55

6-
# 允许可变长参数是 Go 函数另一个很好的特性;我们将在接下来
7-
# 进行学习。
6+
# 我们接下来要学习的是 Go 函数另一个很好的特性:变长参数。

examples/pointers/pointers.go

Lines changed: 7 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,19 @@
11
// Go 支持 <em><a href="http://zh.wikipedia.org/wiki/%E6%8C%87%E6%A8%99_(%E9%9B%BB%E8%85%A6%E7%A7%91%E5%AD%B8)">指针</a></em>,
2-
// 允许在程序中通过引用传递值或者数据结构。
3-
2+
// 允许在程序中通过 `引用传递` 来传递值和数据结构。
43
package main
54

65
import "fmt"
76

8-
// 我们将通过两个函数:`zeroval` 和 `zeroptr` 来比较指针和
9-
// 值类型的不同。`zeroval` 有一个 `int` 型参数,所以使用值
10-
// 传递。`zeroval` 将从调用它的那个函数中得到一个 `ival`
11-
// 形参的拷贝。
7+
// 我们将通过两个函数:`zeroval` 和 `zeroptr` 来比较 `指针` 和 `值`。
8+
// `zeroval` 有一个 `int` 型参数,所以使用值传递。
9+
// `zeroval` 将从调用它的那个函数中得到一个实参的拷贝:ival。
1210
func zeroval(ival int) {
1311
ival = 0
1412
}
1513

16-
// `zeroptr` 有一和上面不同的 `*int` 参数,意味着它用了一
17-
// 个 `int`指针。函数体内的 `*iptr` 接着_解引用_这个指针,
18-
// 从它内存地址得到这个地址对应的当前值。对一个解引用的指
19-
// 针赋值将会改变这个指针引用的真实地址的值。
14+
// `zeroptr` 有一个和上面不同的参数:`*int`,这意味着它使用了 `int` 指针。
15+
// 紧接着,函数体内的 `*iptr` 会 _解引用_ 这个指针,从它的内存地址得到这个地址当前对应的值。
16+
// 对解引用的指针赋值,会改变这个指针引用的真实地址的值。
2017
func zeroptr(iptr *int) {
2118
*iptr = 0
2219
}

examples/pointers/pointers.sh

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
1-
# `zeroval` 在 `main` 函数中不能改变 `i` 的值,但是
2-
# `zeroptr` 可以,因为它有这个变量的内存地址的
3-
# 引用。
1+
# `zeroval` 在 `main` 函数中不能改变 `i` 的值,
2+
# 但是 `zeroptr` 可以,因为它有这个变量的内存地址的引用。
43
$ go run pointers.go
54
initial: 1
65
zeroval: 1

examples/range/range.go

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,13 @@
1-
// _range_ 迭代各种各样的数据结构。让我们来看看如何在我们
2-
// 已经学过的数据结构上使用 `range`。
3-
1+
// _range_ 用于迭代各种各样的数据结构。
2+
// 让我们来看看如何在我们已经学过的数据结构上使用 `range`。
43
package main
54

65
import "fmt"
76

87
func main() {
98

109
// 这里我们使用 `range` 来对 slice 中的元素求和。
11-
// 对于数组也可以采用这种方法
10+
// 数组也可以用这种方法初始化并赋初值
1211
nums := []int{2, 3, 4}
1312
sum := 0
1413
for _, num := range nums {
@@ -17,8 +16,8 @@ func main() {
1716
fmt.Println("sum:", sum)
1817

1918
// `range` 在数组和 slice 中提供对每项的索引和值的访问。
20-
// 上面我们不需要索引,所以我们使用 _空白标识符_
21-
// `_` 来忽略它。有时候我们实际上是需要这个索引的
19+
// 上面我们不需要索引,所以我们使用 _空白标识符_ `_` 将其忽略。
20+
// 实际上,我们有时候是需要这个索引的
2221
for i, num := range nums {
2322
if num == 3 {
2423
fmt.Println("index:", i)

0 commit comments

Comments
 (0)