Skip to content

Commit

Permalink
修改部分描述,添加必要的标点符号,补充代码超链接 (unknwon#804)
Browse files Browse the repository at this point in the history
  • Loading branch information
jckling authored Oct 25, 2021
1 parent d5578df commit 39dbdb7
Show file tree
Hide file tree
Showing 100 changed files with 433 additions and 414 deletions.
4 changes: 2 additions & 2 deletions eBook/04.2.md
Original file line number Diff line number Diff line change
Expand Up @@ -97,15 +97,15 @@ import ("fmt"; "os")

**可见性规则**

当标识符(包括常量、变量、类型、函数名、结构字段等等)以一个大写字母开头,如:Group1,那么使用这种形式的标识符的对象就可以被外部包的代码所使用(客户端程序需要先导入这个包),这被称为导出(像面向对象语言中的 public);标识符如果以小写字母开头,则对包外是不可见的,但是他们在整个包的内部是可见并且可用的(像面向对象语言中的 private )。
当标识符(包括常量、变量、类型、函数名、结构字段等等)以一个大写字母开头,如:Group1,那么使用这种形式的标识符的对象就可以被外部包的代码所使用(客户端程序需要先导入这个包),这被称为导出(像面向对象语言中的 public);标识符如果以小写字母开头,则对包外是不可见的,但是它们在整个包的内部是可见并且可用的(像面向对象语言中的 private )。

(大写字母可以使用任何 Unicode 编码的字符,比如希腊文,不仅仅是 ASCII 码中的大写字母)。

因此,在导入一个外部包后,能够且只能够访问该包中导出的对象。

假设在包 pack1 中我们有一个变量或函数叫做 Thing(以 T 开头,所以它能够被导出),那么在当前包中导入 pack1 包,Thing 就可以像面向对象语言那样使用点标记来调用:`pack1.Thing`(pack1 在这里是不可以省略的)。

因此包也可以作为命名空间使用,帮助避免命名冲突(名称冲突):两个包中的同名变量的区别在于他们的包名,例如 `pack1.Thing``pack2.Thing`
因此包也可以作为命名空间使用,帮助避免命名冲突(名称冲突):两个包中的同名变量的区别在于它们的包名,例如 `pack1.Thing``pack2.Thing`

你可以通过使用包的别名来解决包名之间的名称冲突,或者说根据你的个人喜好对包名进行重新设置,如:`import fm "fmt"`。下面的代码展示了如何使用包的别名:

Expand Down
10 changes: 5 additions & 5 deletions eBook/04.5.md
Original file line number Diff line number Diff line change
Expand Up @@ -40,9 +40,9 @@ aVar != 10 -> false

Go 对于值之间的比较有非常严格的限制,只有两个类型相同的值才可以进行比较,如果值的类型是接口(interface,第 11 章),它们也必须都实现了相同的接口。如果其中一个值是常量,那么另外一个值的类型必须和该常量类型相兼容的。如果以上条件都不满足,则其中一个值的类型必须在被转换为和另外一个值的类型相同之后才可以进行比较。

布尔型的常量和变量也可以通过和逻辑运算符(非 `!` `&&`、或 `||`)结合来产生另外一个布尔值,这样的逻辑语句就其本身而言,并不是一个完整的 Go 语句。
布尔型的常量和变量也可以通过和逻辑运算符(非 `!` `&&`、或 `||`)结合来产生另外一个布尔值,这样的逻辑语句就其本身而言,并不是一个完整的 Go 语句。

逻辑值可以被用于条件结构中的条件语句(第 5 章),以便测试某个条件是否满足。另外, `&&`、或 `||` 与相等 `==` 或不等 `!=` 属于二元运算符,而非 `!` 属于一元运算符。在接下来的内容中,我们会使用 T 来代表条件符合的语句,用 F 来代表条件不符合的语句。
逻辑值可以被用于条件结构中的条件语句(第 5 章),以便测试某个条件是否满足。另外, `&&`、或 `||` 与相等 `==` 或不等 `!=` 属于二元运算符,而非 `!` 属于一元运算符。在接下来的内容中,我们会使用 T 来代表条件符合的语句,用 F 来代表条件不符合的语句。

Go 语言中包含以下逻辑运算符:

Expand Down Expand Up @@ -185,7 +185,7 @@ func main() {

**格式化说明符**

在格式化字符串里,`%d` 用于格式化整数(`%x``%X` 用于格式化 16 进制表示的数字),`%g` 用于格式化浮点型(`%f` 输出浮点数,`%e` 输出科学计数表示法),`%0nd` 用于规定输出长度为n的整数,其中开头的数字 0 是必须的。
在格式化字符串里,`%d` 用于格式化整数(`%x``%X` 用于格式化 16 进制表示的数字),`%g` 用于格式化浮点型(`%f` 输出浮点数,`%e` 输出科学计数表示法),`%0nd` 用于规定输出长度为 n 的整数,其中开头的数字 0 是必须的。

`%n.mg` 用于表示数字 n 并精确到小数点后 m 位,除了使用 g 之外,还可以使用 e 或者 f,例如:使用格式化字符串 `%5.2e` 来输出 3.4 的结果为 `3.40e+00`

Expand Down Expand Up @@ -228,7 +228,7 @@ Go 拥有以下复数类型:
complex64 (32 位实数和虚数)
complex128 (64 位实数和虚数)

复数使用 `re+imI` 来表示,其中 `re` 代表实数部分,`im` 代表虚数部分,I 代表根号负 1。
复数使用 `re+imI` 来表示,其中 `re` 代表实数部分,`im` 代表虚数部分,`I` 代表根号负 1。

示例:

Expand Down Expand Up @@ -369,7 +369,7 @@ b3 := 10 > 5 // b3 is true

**练习 4.4** 尝试编译 [divby0.go](exercises/chapter_4/divby0.go)

你可以将语句 `b = b + a` 简写为 `b+=a`,同样的写法也可用于 `-=``*=``/=``%=`
你可以将语句 `b = b + a` 简写为 `b += a`,同样的写法也可用于 `-=``*=``/=``%=`

对于整数和浮点数,你可以使用一元运算符 `++`(递增)和 `--`(递减),但只能用于后缀:

Expand Down
2 changes: 1 addition & 1 deletion eBook/06.11.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# 6.11 计算函数执行时间

有时候,能够知道一个计算执行消耗的时间是非常有意义的,尤其是在对比和基准测试中。最简单的一个办法就是在计算开始之前设置一个起始时候,再由计算结束时的结束时间,最后取出它们的差值,就是这个计算所消耗的时间。想要实现这样的做法,可以使用 `time` 包中的 `Now()``Sub` 函数:
有时候,能够知道一个计算执行消耗的时间是非常有意义的,尤其是在对比和基准测试中。最简单的一个办法就是在计算开始之前设置一个起始时间,再记录计算结束时的结束时间,最后计算它们的差值,就是这个计算所消耗的时间。想要实现这样的做法,可以使用 `time` 包中的 `Now()``Sub` 函数:

```go
start := time.Now()
Expand Down
2 changes: 1 addition & 1 deletion eBook/06.12.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@

而我们要做就是将第 n 个数的值存在数组中索引为 n 的位置(详见第 7 章),然后在数组中查找是否已经计算过,如果没有找到,则再进行计算。

程序 Listing 6.17 - fibonacci_memoization.go 就是依照这个原则实现的,下面是计算到第 40 位数字的性能对比:
程序 Listing 6.17 - [fibonacci_memoization.go](examples/chapter_6/fibonacci_memoization.go) 就是依照这个原则实现的,下面是计算到第 40 位数字的性能对比:

- 普通写法:4.730270 秒
- 内存缓存:0.001000 秒
Expand Down
2 changes: 1 addition & 1 deletion eBook/06.2.md
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ func MultiPly3Nums(a int, b int, c int) int {

`getX2AndX3``getX2AndX3_2` 两个函数演示了如何使用非命名返回值与命名返回值的特性。当需要返回多个非命名返回值时,需要使用 `()` 把它们括起来,比如 `(int, int)`

命名返回值作为结果形参(result parameters)被初始化为相应类型的零值,当需要返回的时候,我们只需要一条简单的不带参数的return语句。需要注意的是,即使只有一个命名返回值,也需要使用 `()` 括起来(参考 [第 6.6 节](06.6.md)的 fibonacci.go 函数)。
命名返回值作为结果形参(result parameters)被初始化为相应类型的零值,当需要返回的时候,我们只需要一条简单的不带参数的 `return` 语句。需要注意的是,即使只有一个命名返回值,也需要使用 `()` 括起来(参考 [第 6.6 节](06.6.md)的 fibonacci.go 函数)。

示例 6.3 [multiple_return.go](examples/chapter_6/multiple_return.go)

Expand Down
2 changes: 1 addition & 1 deletion eBook/06.7.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# 6.7 将函数作为参数

函数可以作为其它函数的参数进行传递,然后在其它函数内调用执行,一般称之为回调。下面是一个将函数作为参数的简单例子(function_parameter.go):
函数可以作为其它函数的参数进行传递,然后在其它函数内调用执行,一般称之为回调。下面是一个将函数作为参数的简单例子([function_parameter.go](examples/chapter_6/function_parameter.go)):

```go
package main
Expand Down
4 changes: 2 additions & 2 deletions eBook/06.8.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ func() {

表示参数列表的第一对括号必须紧挨着关键字 `func`,因为匿名函数没有名称。花括号 `{}` 涵盖着函数体,最后的一对括号表示对该匿名函数的调用。

下面的例子展示了如何将匿名函数赋值给变量并对其进行调用(function_literal.go):
下面的例子展示了如何将匿名函数赋值给变量并对其进行调用([function_literal.go](examples/chapter_6/function_literal.go)):

```go
package main
Expand Down Expand Up @@ -63,7 +63,7 @@ func (u string) {
}(v)
```

请学习以下示例并思考(return_defer.go):函数 `f` 返回时,变量 `ret` 的值是什么?
请学习以下示例并思考([return_defer.go](examples/chapter_6/return_defer.go)):函数 `f` 返回时,变量 `ret` 的值是什么?

```go
package main
Expand Down
6 changes: 3 additions & 3 deletions eBook/06.9.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# 6.9 应用闭包:将函数作为返回值

在程序 `function_return.go` 中我们将会看到函数 Add2 和 Adder 均会返回签名为 `func(b int) int` 的函数:
在程序 [function_return.go](examples/chapter_6/function_return.go) 中我们将会看到函数 Add2 和 Adder 均会返回签名为 `func(b int) int` 的函数:

```go
func Add2() (func(b int) int)
Expand All @@ -9,7 +9,7 @@ func Adder(a int) (func(b int) int)

函数 Add2 不接受任何参数,但函数 Adder 接受一个 int 类型的整数作为参数。

我们也可以将 Adder 返回的函数存到变量中(function_return.go)。
我们也可以将 Adder 返回的函数存到变量中([function_return.go](examples/chapter_6/function_return.go))。

```go
package main
Expand Down Expand Up @@ -45,7 +45,7 @@ Call Add2 for 3 gives: 5
The result is: 5
```

下例为一个略微不同的实现(function_closure.go):
下例为一个略微不同的实现([function_closure.go](examples/chapter_6/function_closure.go)):

```go
package main
Expand Down
2 changes: 1 addition & 1 deletion eBook/07.0.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# 7.0 数组与切片

这章我们开始剖析 **容器**, 它是可以包含大量条目(item)的数据结构, 例如数组、切片和 map。从这看到 Go 明显受到 Python 的影响。
这章我们开始剖析 **容器**它是可以包含大量条目(item)的数据结构例如数组、切片和 map。从这看到 Go 明显受到 Python 的影响。

`[]` 符号标识的数组类型几乎在所有的编程语言中都是一个基本主力。Go 语言中的数组也是类似的,只是有一些特点。Go 没有 C 那么灵活,但是拥有切片(slice)类型。这是一种建立在 Go 语言数组类型之上的抽象,要想理解切片我们必须先理解数组。数组有特定的用处,但是却有一些呆板,所以在 Go 语言的代码里并不是特别常见。相对的,切片确实随处可见的。它们构建在数组之上并且提供更强大的能力和便捷。

Expand Down
12 changes: 6 additions & 6 deletions eBook/07.1.md
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
# 7.1 声明和初始化

## 7.1.1 概念
数组是具有相同 **唯一类型** 的一组已编号且长度固定的数据项序列(这是一种同构的数据结构);这种类型可以是任意的原始类型例如整型、字符串或者自定义类型。数组长度必须是一个常量表达式,并且必须是一个非负整数。数组长度也是数组类型的一部分,所以[5]int和[10]int是属于不同类型的。数组的编译时值初始化是按照数组顺序完成的(如下)。
数组是具有相同 **唯一类型** 的一组已编号且长度固定的数据项序列(这是一种同构的数据结构);这种类型可以是任意的原始类型例如整型、字符串或者自定义类型。数组长度必须是一个常量表达式,并且必须是一个非负整数。数组长度也是数组类型的一部分,所以 `[5]int``[10]int` 是属于不同类型的。数组的编译时值初始化是按照数组顺序完成的(如下)。

**注意事项** 如果我们想让数组元素类型为任意类型的话可以使用空接口作为类型(参考 [第 11 章](11.9.md))。当使用值时我们必须先做一个类型判断(参考 [第 11 章](11.3.md))。

数组元素可以通过 **索引**(位置)来读取(或者修改),索引从 0 开始,第一个元素索引为 0,第二个索引为 1,以此类推。(数组以 0 开始在所有类 C 语言中是相似的)。元素的数目,也称为长度或者数组大小必须是固定的并且在声明该数组时就给出(编译时需要知道数组长度以便分配内存);数组长度最大为 2Gb
数组元素可以通过 **索引**(位置)来读取(或者修改),索引从 0 开始,第一个元素索引为 0,第二个索引为 1,以此类推。(数组以 0 开始在所有类 C 语言中是相似的)。元素的数目(也称为长度或者数组大小)必须是固定的并且在声明该数组时就给出(编译时需要知道数组长度以便分配内存);数组长度最大为 2GB

声明的格式是:

Expand Down Expand Up @@ -33,7 +33,7 @@ arr1 的长度是 5,索引范围从 0 到 `len(arr1)-1`。

runtime error: index out of range

由于索引的存在,遍历数组的方法自然就是使用 for 结构:
由于索引的存在,遍历数组的方法自然就是使用 for 结构

- 通过 for 初始化数组项
- 通过 for 打印数组元素
Expand Down Expand Up @@ -99,7 +99,7 @@ for i := range a {

Go 语言中的数组是一种 **值类型**(不像 C/C++ 中是指向首元素的指针),所以可以通过 `new()` 来创建: `var arr1 = new([5]int)`

那么这种方式和 `var arr2 [5]int` 的区别是什么呢?arr1 的类型是 `*[5]int`,而 arr2的类型是 `[5]int`
那么这种方式和 `var arr2 [5]int` 的区别是什么呢?arr1 的类型是 `*[5]int`,而 arr2 的类型是 `[5]int`

这样的结果就是当把一个数组赋值给另一个时,需要再做一次数组内存的拷贝操作。例如:

Expand Down Expand Up @@ -181,7 +181,7 @@ var arrAge = [5]int{18, 20, 15, 22, 16}
var arrLazy = [...]int{5, 6, 7, 8, 22}
```

`...` 可同样可以忽略,从技术上说它们其实变化成了切片
`...` 同样可以忽略,从技术上说它们其实变成了切片

第三种变化:`key: value 语法`

Expand Down Expand Up @@ -258,7 +258,7 @@ func main() {

## 7.1.4 将数组传递给函数

把一个大数组传递给函数会消耗很多内存。有两种方法可以避免这种现象
把一个大数组传递给函数会消耗很多内存。有两种方法可以避免这种情况

- 传递数组的指针
- 使用数组的切片
Expand Down
Loading

0 comments on commit 39dbdb7

Please sign in to comment.