fix: fix a lot of incorrect links (#849)

This commit is contained in:
Rethan
2022-06-25 18:18:09 +08:00
committed by GitHub
parent 8f1ca5772e
commit 7a54d34d36
28 changed files with 69 additions and 69 deletions

View File

@@ -26,7 +26,7 @@ func main() {
在 Go 的安装文件里包含了一些可以直接使用的包,即标准库。在 Windows 下,标准库的位置在 Go 根目录下的子目录 `pkg\windows_386` 中;在 Linux 下,标准库在 Go 根目录下的子目录 `pkg\linux_amd64` 中(如果是安装的是 32 位,则在 `linux_386` 目录中)。一般情况下,标准包会存放在 `$GOROOT/pkg/$GOOS_$GOARCH/` 目录下。 在 Go 的安装文件里包含了一些可以直接使用的包,即标准库。在 Windows 下,标准库的位置在 Go 根目录下的子目录 `pkg\windows_386` 中;在 Linux 下,标准库在 Go 根目录下的子目录 `pkg\linux_amd64` 中(如果是安装的是 32 位,则在 `linux_386` 目录中)。一般情况下,标准包会存放在 `$GOROOT/pkg/$GOOS_$GOARCH/` 目录下。
Go 的标准库包含了大量的包(如:`fmt``os`),但是你也可以创建自己的包([第 9 章](.\09.0.md))。 Go 的标准库包含了大量的包(如:`fmt``os`),但是你也可以创建自己的包([第 9 章](./09.0.md))。
如果想要构建一个程序,则包和包内的文件都必须以正确的顺序进行编译。包的依赖关系决定了其构建顺序。 如果想要构建一个程序,则包和包内的文件都必须以正确的顺序进行编译。包的依赖关系决定了其构建顺序。

View File

@@ -64,7 +64,7 @@ const (
) )
``` ```
现在,数字 `0``1``2` 分别代表未知性别、女性和男性。这些枚举值可以用于测试某个变量或常量的实际值,比如使用 switch/case 结构([第 5.3 节](.\05.3.md))。 现在,数字 `0``1``2` 分别代表未知性别、女性和男性。这些枚举值可以用于测试某个变量或常量的实际值,比如使用 switch/case 结构([第 5.3 节](./05.3.md))。
在这个例子中,`iota` 可以被用作枚举值: 在这个例子中,`iota` 可以被用作枚举值:

View File

@@ -136,7 +136,7 @@ func main() {
如果你在 Windows 下运行这段代码,则会输出 `The operating system is: windows` 以及相应的环境变量的值;如果你在 Linux 下运行这段代码,则会输出 `The operating system is: linux` 以及相应的的环境变量的值。 如果你在 Windows 下运行这段代码,则会输出 `The operating system is: windows` 以及相应的环境变量的值;如果你在 Linux 下运行这段代码,则会输出 `The operating system is: linux` 以及相应的的环境变量的值。
这里用到了 `Printf` 的格式化输出的功能([第 4.4.3 节](.\04.4.md))。 这里用到了 `Printf` 的格式化输出的功能([第 4.4.3 节](./04.4.md))。
## 4.4.2 值类型和引用类型 ## 4.4.2 值类型和引用类型
@@ -146,13 +146,13 @@ func main() {
<img src="images/4.4.2_fig4.1.jpg?raw=true" style="zoom:67%;" /> <img src="images/4.4.2_fig4.1.jpg?raw=true" style="zoom:67%;" />
另外,像数组([第 7 章](.\07.0.md))和结构([第 10 章](.\10.0md))这些复合类型也是值类型。 另外,像数组([第 7 章](./07.0.md))和结构([第 10 章](./10.0md))这些复合类型也是值类型。
当使用等号 `=` 将一个变量的值赋值给另一个变量时,如:`j = i`,实际上是在内存中将 `i` 的值进行了拷贝: 当使用等号 `=` 将一个变量的值赋值给另一个变量时,如:`j = i`,实际上是在内存中将 `i` 的值进行了拷贝:
<img src="images/4.4.2_fig4.2.jpg?raw=true" style="zoom: 67%;" /> <img src="images/4.4.2_fig4.2.jpg?raw=true" style="zoom: 67%;" />
你可以通过 `&i` 来获取变量 `i` 的内存地址([第 4.9 节](.\04.9.md)),例如:`0xf840000040`(每次的地址都可能不一样)。值类型的变量的值存储在栈中。 你可以通过 `&i` 来获取变量 `i` 的内存地址([第 4.9 节](./04.9.md)),例如:`0xf840000040`(每次的地址都可能不一样)。值类型的变量的值存储在栈中。
内存地址会根据机器的不同而有所不同,甚至相同的程序在不同的机器上执行后也会有不同的内存地址。因为每台机器可能有不同的存储器布局,并且位置分配也可能不同。 内存地址会根据机器的不同而有所不同,甚至相同的程序在不同的机器上执行后也会有不同的内存地址。因为每台机器可能有不同的存储器布局,并且位置分配也可能不同。
@@ -162,7 +162,7 @@ func main() {
<img src="images/4.4.2_fig4.3.jpg?raw=true" style="zoom:67%;" /> <img src="images/4.4.2_fig4.3.jpg?raw=true" style="zoom:67%;" />
这个内存地址被称之为指针(你可以从上图中很清晰地看到,[第 4.9 节](.\04.9.md) 将会详细说明),这个指针实际上也被存在另外的某一个字中。 这个内存地址被称之为指针(你可以从上图中很清晰地看到,[第 4.9 节](./04.9.md) 将会详细说明),这个指针实际上也被存在另外的某一个字中。
同一个引用类型的指针指向的多个字可以是在连续的内存地址中(内存布局是连续的),这也是计算效率最高的一种存储形式;也可以将这些字分散存放在内存中,每个字都指示了下一个字所在的内存地址。 同一个引用类型的指针指向的多个字可以是在连续的内存地址中(内存布局是连续的),这也是计算效率最高的一种存储形式;也可以将这些字分散存放在内存中,每个字都指示了下一个字所在的内存地址。
@@ -170,7 +170,7 @@ func main() {
如果 `r1` 的值被改变了,那么这个值的所有引用都会指向被修改后的内容,在这个例子中,`r2` 也会受到影响。 如果 `r1` 的值被改变了,那么这个值的所有引用都会指向被修改后的内容,在这个例子中,`r2` 也会受到影响。
在 Go 语言中,指针([第 4.9 节](.\04.9.md))属于引用类型,其它的引用类型还包括 slices[第 7 章](07.0.md)maps[第 8 章](08.0.md))和 channel[第 13 章](13.0.md))。被引用的变量会存储在堆中,以便进行垃圾回收,且比栈拥有更大的内存空间。 在 Go 语言中,指针([第 4.9 节](./04.9.md))属于引用类型,其它的引用类型还包括 slices[第 7 章](07.0.md)maps[第 8 章](08.0.md))和 channel[第 13 章](13.0.md))。被引用的变量会存储在堆中,以便进行垃圾回收,且比栈拥有更大的内存空间。
## 4.4.3 打印 ## 4.4.3 打印

View File

@@ -217,7 +217,7 @@ func IntFromFloat64(x float64) int {
} }
``` ```
不过如果你实际存的数字超出你要转换到的类型的取值范围的话,则会引发 `panic`[第 13.2 节](.\13.2.md))。 不过如果你实际存的数字超出你要转换到的类型的取值范围的话,则会引发 `panic`[第 13.2 节](./13.2.md))。
**问题 4.1** `int``int64` 是相同的类型吗? **问题 4.1** `int``int64` 是相同的类型吗?
@@ -468,7 +468,7 @@ func main() {
} }
``` ```
实际上,类型别名得到的新类型并非和原类型完全相同,新类型不会拥有原类型所附带的方法([第 10 章](.\10.0.md)`TZ` 可以自定义一个方法用来输出更加人性化的时区信息。 实际上,类型别名得到的新类型并非和原类型完全相同,新类型不会拥有原类型所附带的方法([第 10 章](./10.0.md)`TZ` 可以自定义一个方法用来输出更加人性化的时区信息。
**练习 4.5** 定义一个 `string` 的类型别名 `Rope`,并声明一个该类型的变量。 **练习 4.5** 定义一个 `string` 的类型别名 `Rope`,并声明一个该类型的变量。
@@ -511,7 +511,7 @@ fmt.Printf("%U - %U - %U", ch, ch2, ch3) // UTF-8 code point
41 - 3B2 - 101234 41 - 3B2 - 101234
U+0041 - U+03B2 - U+101234 U+0041 - U+03B2 - U+101234
格式化说明符 `%c` 用于表示字符;当和字符配合使用时,`%v``%d` 会输出用于表示该字符的整数;`%U` 输出格式为 `U+hhhh` 的字符串(另一个示例见[第 5.4.4 节](.\05.4.md))。 格式化说明符 `%c` 用于表示字符;当和字符配合使用时,`%v``%d` 会输出用于表示该字符的整数;`%U` 输出格式为 `U+hhhh` 的字符串(另一个示例见[第 5.4.4 节](./05.4.md))。
`unicode` 包含了一些针对测试字符的非常有用的函数(其中 `ch` 代表字符): `unicode` 包含了一些针对测试字符的非常有用的函数(其中 `ch` 代表字符):

View File

@@ -63,7 +63,7 @@ fmt.Println(s) //输出 “hello, world!”
在循环中使用加号 `+` 拼接字符串并不是最高效的做法,更好的办法是使用函数 `strings.Join()`[第 4.7.10 节](04.7.md)),有没有更好的办法了?有!使用字节缓冲(`bytes.Buffer`)拼接更加给力([第 7.2.6 节](07.2.md) 在循环中使用加号 `+` 拼接字符串并不是最高效的做法,更好的办法是使用函数 `strings.Join()`[第 4.7.10 节](04.7.md)),有没有更好的办法了?有!使用字节缓冲(`bytes.Buffer`)拼接更加给力([第 7.2.6 节](07.2.md)
在[第 7 章](07.0.md),我们会讲到通过将字符串看作是字节 (`byte`) 的切片 (slice) 来实现对其标准索引法的操作。会在[第 5.4.1 节](05.4.md) 中讲到的 `for` 循环只会根据索引返回字符串中的纯字节,而在[第 5.4.4 节](.\05.4.md)(以及[第 7.6.1 节](07.6.md) 的示例)将会展示如何使用 for-range 循环来实现对 Unicode 字符串的迭代操作。在下一节,我们会学习到许多有关字符串操作的函数和方法,同时 `fmt` 包中的 `fmt.Sprint(x)` 也可以格式化生成并返回你所需要的字符串([第 4.4.3 节](04.3.md))。 在[第 7 章](07.0.md),我们会讲到通过将字符串看作是字节 (`byte`) 的切片 (slice) 来实现对其标准索引法的操作。会在[第 5.4.1 节](05.4.md) 中讲到的 `for` 循环只会根据索引返回字符串中的纯字节,而在[第 5.4.4 节](./05.4.md)(以及[第 7.6.1 节](07.6.md) 的示例)将会展示如何使用 for-range 循环来实现对 Unicode 字符串的迭代操作。在下一节,我们会学习到许多有关字符串操作的函数和方法,同时 `fmt` 包中的 `fmt.Sprint(x)` 也可以格式化生成并返回你所需要的字符串([第 4.4.3 节](04.3.md))。
**练习 4.6** [count_characters.go](exercises/chapter_4/count_characters.go) **练习 4.6** [count_characters.go](exercises/chapter_4/count_characters.go)

View File

@@ -75,7 +75,7 @@ func main() {
It's equal to 100 It's equal to 100
在第 12.1 节,我们会使用 `switch` 语句判断从键盘输入的字符(详见[第 12.2 节](12.2.md) 的 [switch.go](.\examples\chapter_12\switch.go))。`switch` 语句的第二种形式是不提供任何被判断的值(实际上默认为判断是否为 `true`),然后在每个 `case` 分支中进行测试不同的条件。当任一分支的测试结果为 `true` 时,该分支的代码会被执行。这看起来非常像链式的 if-else 语句,但是在测试条件非常多的情况下,提供了可读性更好的书写方式。 在第 12.1 节,我们会使用 `switch` 语句判断从键盘输入的字符(详见[第 12.2 节](12.2.md) 的 [switch.go](./examples/chapter_12/switch.go))。`switch` 语句的第二种形式是不提供任何被判断的值(实际上默认为判断是否为 `true`),然后在每个 `case` 分支中进行测试不同的条件。当任一分支的测试结果为 `true` 时,该分支的代码会被执行。这看起来非常像链式的 if-else 语句,但是在测试条件非常多的情况下,提供了可读性更好的书写方式。
```go ```go
switch { switch {

View File

@@ -46,7 +46,7 @@ func main() {
for i, j := 0, N; i < j; i, j = i+1, j-1 {} for i, j := 0, N; i < j; i, j = i+1, j-1 {}
``` ```
这得益于 Go 语言具有的平行赋值的特性(可以查看[第 7 章](07.0.md) [string_reverse.go](.\examples\chapter_7\string_reverse.go) 中反转数组的示例)。 这得益于 Go 语言具有的平行赋值的特性(可以查看[第 7 章](07.0.md) [string_reverse.go](./examples/chapter_7/string_reverse.go) 中反转数组的示例)。
您可以将两个 for 循环嵌套起来: 您可以将两个 for 循环嵌套起来:

View File

@@ -53,7 +53,7 @@ func main() {
**特别注意** 使用标签和 `goto` 语句是不被鼓励的:它们会很快导致非常糟糕的程序设计,而且总有更加可读的替代方案来实现相同的需求。 **特别注意** 使用标签和 `goto` 语句是不被鼓励的:它们会很快导致非常糟糕的程序设计,而且总有更加可读的替代方案来实现相同的需求。
一个建议使用 `goto` 语句的示例会在[第 15.1 章](15.1.md) 的 [simple_tcp_server.go](.\examples\chapter_15\simple_tcp_server.go) 中出现:示例中在发生读取错误时,使用 goto 来跳出无限读取循环并关闭相应的客户端链接。 一个建议使用 `goto` 语句的示例会在[第 15.1 章](15.1.md) 的 [simple_tcp_server.go](./examples/chapter_15/simple_tcp_server.go) 中出现:示例中在发生读取错误时,使用 goto 来跳出无限读取循环并关闭相应的客户端链接。
定义但未使用标签会导致编译错误:`label … defined and not used` 定义但未使用标签会导致编译错误:`label … defined and not used`

View File

@@ -84,7 +84,7 @@ func MultiPly3Nums(a int, b int, c int) int {
`getX2AndX3``getX2AndX3_2` 两个函数演示了如何使用非命名返回值与命名返回值的特性。当需要返回多个非命名返回值时,需要使用 `()` 把它们括起来,比如 `(int, int)` `getX2AndX3``getX2AndX3_2` 两个函数演示了如何使用非命名返回值与命名返回值的特性。当需要返回多个非命名返回值时,需要使用 `()` 把它们括起来,比如 `(int, int)`
命名返回值作为结果形参 (result parameters) 被初始化为相应类型的零值,当需要返回的时候,我们只需要一条简单的不带参数的 `return` 语句。需要注意的是,即使只有一个命名返回值,也需要使用 `()` 括起来(参考[第 6.6 节](06.6.md) 的 [fibonacci.go](.\examples\chapter_6\fibonacci.go) 函数)。 命名返回值作为结果形参 (result parameters) 被初始化为相应类型的零值,当需要返回的时候,我们只需要一条简单的不带参数的 `return` 语句。需要注意的是,即使只有一个命名返回值,也需要使用 `()` 括起来(参考[第 6.6 节](06.6.md) 的 [fibonacci.go](./examples/chapter_6/fibonacci.go) 函数)。
示例 6.3 [multiple_return.go](examples/chapter_6/multiple_return.go) 示例 6.3 [multiple_return.go](examples/chapter_6/multiple_return.go)

View File

@@ -53,7 +53,7 @@ func min(s ...int) int {
The minimum is: 0 The minimum is: 0
The minimum in the slice is: 1 The minimum in the slice is: 1
**练习 6.3** [varargs.go](exercises\chapter_6\varargs.go) **练习 6.3** [varargs.go](exercises/chapter_6/varargs.go)
写一个函数,该函数接受一个变长参数并对每个元素进行换行打印。 写一个函数,该函数接受一个变长参数并对每个元素进行换行打印。

View File

@@ -92,15 +92,15 @@ func RevSign(nr int) int {
### 练习题 ### 练习题
**练习 6.4** [fibonacci2.go](exercises\chapter_6\fibonacci2.go) **练习 6.4** [fibonacci2.go](exercises/chapter_6/fibonacci2.go)
重写本节中生成斐波那契数列的程序并返回两个命名返回值(详见[第 6.2 节](06.2.md)),即数列中的位置和对应的值,例如 5 与 489 与 10。 重写本节中生成斐波那契数列的程序并返回两个命名返回值(详见[第 6.2 节](06.2.md)),即数列中的位置和对应的值,例如 5 与 489 与 10。
**练习 6.5** [10to1_recursive.go](exercises\chapter_6\10to1_recursive.go) **练习 6.5** [10to1_recursive.go](exercises/chapter_6/10to1_recursive.go)
使用递归函数从 10 打印到 1。 使用递归函数从 10 打印到 1。
**练习 6.6** [factorial.go](exercises\chapter_6\factorial.go) **练习 6.6** [factorial.go](exercises/chapter_6/factorial.go)
实现一个输出前 30 个整数的阶乘的程序。 实现一个输出前 30 个整数的阶乘的程序。

View File

@@ -95,7 +95,7 @@ go func(i int) {
这样闭包函数就能够被应用到整个集合的元素上,并修改它们的值。然后这些变量就可以用于表示或计算全局或平均值。 这样闭包函数就能够被应用到整个集合的元素上,并修改它们的值。然后这些变量就可以用于表示或计算全局或平均值。
**练习 6.9** [fibonacci_closure](exercises\chapter_6\fibonacci_closure.go) **练习 6.9** [fibonacci_closure](exercises/chapter_6/fibonacci_closure.go)
不使用递归但使用闭包改写第 6.6 节中的斐波那契数列程序。 不使用递归但使用闭包改写第 6.6 节中的斐波那契数列程序。

View File

@@ -138,15 +138,15 @@ func main() {
**练习** **练习**
练习7.1[array_value.go](examples\chapter_7\array_value.go): 练习7.1[array_value.go](examples/chapter_7/array_value.go):
证明当数组赋值时,发生了数组内存拷贝。 证明当数组赋值时,发生了数组内存拷贝。
练习7.2[for_array.go](examples\chapter_7\for_array.go): 练习7.2[for_array.go](examples/chapter_7/for_array.go):
写一个循环并用下标给数组赋值(从 0 到 15并且将数组打印在屏幕上。 写一个循环并用下标给数组赋值(从 0 到 15并且将数组打印在屏幕上。
练习7.3[fibonacci_array.go](examples\chapter_7\fibonacci_array.go): 练习7.3[fibonacci_array.go](examples/chapter_7/fibonacci_array.go):
在[第 6.6 节](06.6.md) 我们看到了一个递归计算 Fibonacci 数值的方法。但是通过数组我们可以更快的计算出 Fibonacci 数。完成该方法并打印出前 50 个 Fibonacci 数字。 在[第 6.6 节](06.6.md) 我们看到了一个递归计算 Fibonacci 数值的方法。但是通过数组我们可以更快的计算出 Fibonacci 数。完成该方法并打印出前 50 个 Fibonacci 数字。

View File

@@ -176,15 +176,15 @@ func FindFileDigits(filename string) []byte {
} }
``` ```
**练习 7.12** [split_string.go](exercises\chapter_7\split_string.go) **练习 7.12** [split_string.go](exercises/chapter_7/split_string.go)
编写一个函数,要求其接受两个参数,原始字符串 `str` 和分割索引 `i`,然后返回两个分割后的字符串。 编写一个函数,要求其接受两个参数,原始字符串 `str` 和分割索引 `i`,然后返回两个分割后的字符串。
**练习 7.13** [string_split2.go](exercises\chapter_7\string_split2.go) **练习 7.13** [string_split2.go](exercises/chapter_7/string_split2.go)
假设有字符串 `str`,那么 `str[len(str)/2:] + str[:len(str)/2]` 的结果是什么? 假设有字符串 `str`,那么 `str[len(str)/2:] + str[:len(str)/2]` 的结果是什么?
**练习 7.14** [string_reverse.go](exercises\chapter_7\string_reverse.go) **练习 7.14** [string_reverse.go](exercises/chapter_7/string_reverse.go)
编写一个程序,要求能够反转字符串,即将 `"Google"` 转换成 `"elgooG"`(提示:使用 `[]byte` 类型的切片)。 编写一个程序,要求能够反转字符串,即将 `"Google"` 转换成 `"elgooG"`(提示:使用 `[]byte` 类型的切片)。
@@ -192,15 +192,15 @@ func FindFileDigits(filename string) []byte {
如果您想要反转 Unicode 编码的字符串,请使用 `[]int32` 类型的切片。 如果您想要反转 Unicode 编码的字符串,请使用 `[]int32` 类型的切片。
**练习 7.15** [Q29_uniq.go](exercises\chapter_7\uniq.go) **练习 7.15** [Q29_uniq.go](exercises/chapter_7/uniq.go)
编写一个程序,要求能够遍历一个字符数组,并将当前字符和前一个字符不相同的字符拷贝至另一个数组。 编写一个程序,要求能够遍历一个字符数组,并将当前字符和前一个字符不相同的字符拷贝至另一个数组。
**练习 7.16** [bubblesort.go](exercises\chapter_7\bubblesort.go) **练习 7.16** [bubblesort.go](exercises/chapter_7/bubblesort.go)
编写一个程序,使用冒泡排序的方法排序一个包含整数的切片(算法的定义可参考 [维基百科](http://en.wikipedia.org/wiki/Bubble_sort))。 编写一个程序,使用冒泡排序的方法排序一个包含整数的切片(算法的定义可参考 [维基百科](http://en.wikipedia.org/wiki/Bubble_sort))。
**练习 7.17** [map_function.go](exercises\chapter_7\map_function.go) **练习 7.17** [map_function.go](exercises/chapter_7/map_function.go)
在函数式编程语言中,一个 map-function 是指能够接受一个函数原型和一个列表,并使用列表中的值依次执行函数原型,公式为:`map ( F(), (e1,e2, . . . ,en) ) = ( F(e1), F(e2), ... F(en) )`。 在函数式编程语言中,一个 map-function 是指能够接受一个函数原型和一个列表,并使用列表中的值依次执行函数原型,公式为:`map ( F(), (e1,e2, . . . ,en) ) = ( F(e1), F(e2), ... F(en) )`。

View File

@@ -62,7 +62,7 @@ for key := range capitals {
} }
``` ```
**练习 8.1** [map_days.go](exercises\chapter_8\map_days.go) **练习 8.1** [map_days.go](exercises/chapter_8/map_days.go)
创建一个 `map` 来保存每周 7 天的名字,将它们打印出来并且测试是否存在 `"Tuesday"``"Hollyday"` 创建一个 `map` 来保存每周 7 天的名字,将它们打印出来并且测试是否存在 `"Tuesday"``"Hollyday"`

View File

@@ -36,7 +36,7 @@ func main() {
如果原始 value 值不唯一那这么做肯定会出问题;这种情况下不会报错,但是当遇到不唯一的 key 时应当直接停止对调,且此时对调后的 `map` 很可能没有包含原 `map` 的所有键值对!一种解决方法就是仔细检查唯一性并且使用多值 `map`,比如使用 `map[int][]string` 类型。 如果原始 value 值不唯一那这么做肯定会出问题;这种情况下不会报错,但是当遇到不唯一的 key 时应当直接停止对调,且此时对调后的 `map` 很可能没有包含原 `map` 的所有键值对!一种解决方法就是仔细检查唯一性并且使用多值 `map`,比如使用 `map[int][]string` 类型。
**练习 8.2** [map_drinks.go](exercises\chapter_8\map_drinks.go) **练习 8.2** [map_drinks.go](exercises/chapter_8/map_drinks.go)
构造一个将英文饮料名映射为法语(或者任意你的母语)的集合;先打印所有的饮料,然后打印原名和翻译后的名字。接下来按照英文名排序后再打印出来。 构造一个将英文饮料名映射为法语(或者任意你的母语)的集合;先打印所有的饮料,然后打印原名和翻译后的名字。接下来按照英文名排序后再打印出来。

View File

@@ -80,11 +80,11 @@ for e := l.Front(); e != nil; e = e.Next() {
`exp` 包中有许多将被编译为新包的实验性的包。在下次稳定版本发布的时候,它们将成为独立的包。如果前一个版本已经存在了,它们将被作为过时的包被回收。然而 Go1.0 发布的时候并没有包含过时或者实验性的包。 `exp` 包中有许多将被编译为新包的实验性的包。在下次稳定版本发布的时候,它们将成为独立的包。如果前一个版本已经存在了,它们将被作为过时的包被回收。然而 Go1.0 发布的时候并没有包含过时或者实验性的包。
**练习 9.1** [Q20_linked_list.go](exercises\chapter_9\dlinked_list.go) **练习 9.1** [Q20_linked_list.go](exercises/chapter_9/dlinked_list.go)
使用 `container/list` 包实现一个双向链表,将 `101``102``103` 放入其中并打印出来。 使用 `container/list` 包实现一个双向链表,将 `101``102``103` 放入其中并打印出来。
**练习 9.2** [size_int.go](exercises\chapter_9\size_int.go) **练习 9.2** [size_int.go](exercises/chapter_9/size_int.go)
通过使用 `unsafe` 包中的方法来测试你电脑上一个整型变量占用多少个字节。 通过使用 `unsafe` 包中的方法来测试你电脑上一个整型变量占用多少个字节。

View File

@@ -152,7 +152,7 @@ a一个包能分成多个源文件么
b一个源文件是否能包含多个包 b一个源文件是否能包含多个包
**练习 9.3** [main_greetings.go](exercises\chapter_9\main_greetings.go) **练习 9.3** [main_greetings.go](exercises/chapter_9/main_greetings.go)
创建一个程序 main_greetings.go 能够和用户说 `"Good Day"` 或者 `"Good Night"`。不同的问候应该放到单独的 `greetings` 包中。 创建一个程序 main_greetings.go 能够和用户说 `"Good Day"` 或者 `"Good Night"`。不同的问候应该放到单独的 `greetings` 包中。
@@ -160,7 +160,7 @@ b一个源文件是否能包含多个包
使用 main_greetings 作出合适的问候(提示:使用 `time` 包)。 使用 main_greetings 作出合适的问候(提示:使用 `time` 包)。
**练习 9.4** 创建一个程序 [main_oddven.go](exercises\chapter_9\main_oddeven.go) 判断前 100 个整数是不是偶数,将判断所用的函数编写在 `even` 包里。 **练习 9.4** 创建一个程序 [main_oddven.go](exercises/chapter_9/main_oddeven.go) 判断前 100 个整数是不是偶数,将判断所用的函数编写在 `even` 包里。
**练习 9.5** 使用[第 6.6 节](06.6.md)的斐波那契程序: **练习 9.5** 使用[第 6.6 节](06.6.md)的斐波那契程序:
@@ -169,7 +169,7 @@ b一个源文件是否能包含多个包
2扩展 `fibo` 包将通过调用斐波那契的时候,操作也作为一个参数。实验 `"+"``"*"` 2扩展 `fibo` 包将通过调用斐波那契的时候,操作也作为一个参数。实验 `"+"``"*"`
[main_fibo.go](exercises\chapter_9\main_fibo.go) / [fibonacci.go](exercises/chapter_6/fibonacci.go) [main_fibo.go](exercises/chapter_9/main_fibo.go) / [fibonacci.go](exercises/chapter_6/fibonacci.go)
## 链接 ## 链接

View File

@@ -278,7 +278,7 @@ func main() {
{5} {5} {5} {5} {5} {5}
**练习 10.1** [vcard.go](exercises\chapter_10\vcard.go) **练习 10.1** [vcard.go](exercises/chapter_10/vcard.go)
定义结构体 `Address``VCard`,后者包含一个人的名字、地址编号、出生日期和图像,试着选择正确的数据类型。构建一个自己的 `vcard` 并打印它的内容。 定义结构体 `Address``VCard`,后者包含一个人的名字、地址编号、出生日期和图像,试着选择正确的数据类型。构建一个自己的 `vcard` 并打印它的内容。
@@ -287,15 +287,15 @@ func main() {
第二种会好点,因为它占用内存少。包含一个名字和两个指向地址的指针的 Address 结构体可以使用 %v 打印: 第二种会好点,因为它占用内存少。包含一个名字和两个指向地址的指针的 Address 结构体可以使用 %v 打印:
{Kersschot 0x126d2b80 0x126d2be0} {Kersschot 0x126d2b80 0x126d2be0}
**练习 10.2** [personex1.go](exercises\chapter_10\personex1.go) **练习 10.2** [personex1.go](exercises/chapter_10/personex1.go)
修改 personex1.go使它的参数 `upPerson` 不是一个指针,解释下二者的区别。 修改 personex1.go使它的参数 `upPerson` 不是一个指针,解释下二者的区别。
**练习 10.3** [point.go](exercises\chapter_10\point.go) **练习 10.3** [point.go](exercises/chapter_10/point.go)
使用坐标 `X``Y` 定义一个二维 `Point` 结构体。同样地,对一个三维点使用它的极坐标定义一个 `Polar` 结构体。实现一个 `Abs()` 方法来计算一个 `Point` 表示的向量的长度,实现一个 `Scale()` 方法,它将点的坐标乘以一个尺度因子(提示:使用 `math` 包里的 `Sqrt()` 函数)(function Scale that multiplies the coordinates of a point with a scale factor)。 使用坐标 `X``Y` 定义一个二维 `Point` 结构体。同样地,对一个三维点使用它的极坐标定义一个 `Polar` 结构体。实现一个 `Abs()` 方法来计算一个 `Point` 表示的向量的长度,实现一个 `Scale()` 方法,它将点的坐标乘以一个尺度因子(提示:使用 `math` 包里的 `Sqrt()` 函数)(function Scale that multiplies the coordinates of a point with a scale factor)。
**练习 10.4** [rectangle.go](exercises\chapter_10\rectangle.go) **练习 10.4** [rectangle.go](exercises/chapter_10/rectangle.go)
定义一个 `Rectangle` 结构体,它的长和宽是 `int` 类型,并定义方法 `Area()``Perimeter()`,然后进行测试。 定义一个 `Rectangle` 结构体,它的长和宽是 `int` 类型,并定义方法 `Area()``Perimeter()`,然后进行测试。

View File

@@ -92,7 +92,7 @@ func main() {
1 2 3 4 1 2 3 4
{1 2} {1 2}
**练习 10.5** [anonymous_struct.go](exercises\chapter_10\anonymous_struct.go) **练习 10.5** [anonymous_struct.go](exercises/chapter_10/anonymous_struct.go)
创建一个结构体,它有一个具名的 `float32` 字段2 个匿名字段,类型分别是 `int``string`。通过结构体字面量新建一个结构体实例并打印它的内容。 创建一个结构体,它有一个具名的 `float32` 字段2 个匿名字段,类型分别是 `int``string`。通过结构体字面量新建一个结构体实例并打印它的内容。

View File

@@ -103,11 +103,11 @@ func main() {
} }
``` ```
**练习 10.6** [employee_salary.go](exercises\chapter_10\employee_salary.go) **练习 10.6** [employee_salary.go](exercises/chapter_10/employee_salary.go)
定义结构体 `employee`,它有一个 `salary` 字段,给这个结构体定义一个方法 `giveRaise` 来按照指定的百分比增加薪水。 定义结构体 `employee`,它有一个 `salary` 字段,给这个结构体定义一个方法 `giveRaise` 来按照指定的百分比增加薪水。
**练习 10.7** [iteration_list.go](exercises\chapter_10\iteration_list.go) **练习 10.7** [iteration_list.go](exercises/chapter_10/iteration_list.go)
下面这段代码有什么错? 下面这段代码有什么错?
@@ -415,7 +415,7 @@ func (n *NamedPoint) Abs() float64 {
结构体内嵌和自己在同一个包中的结构体时,可以彼此访问对方所有的字段和方法。 结构体内嵌和自己在同一个包中的结构体时,可以彼此访问对方所有的字段和方法。
**练习 10.8** [inheritance_car.go](exercises\chapter_10\inheritance_car.go) **练习 10.8** [inheritance_car.go](exercises/chapter_10/inheritance_car.go)
创建一个上面 `Car``Engine` 可运行的例子,并且给 `Car` 类型一个 `wheelCount` 字段和一个 `numberOfWheels()` 方法。 创建一个上面 `Car``Engine` 可运行的例子,并且给 `Car` 类型一个 `wheelCount` 字段和一个 `numberOfWheels()` 方法。
@@ -581,17 +581,17 @@ func main() {
It exhibits behavior of a Camera: Click It exhibits behavior of a Camera: Click
It works like a Phone too: Ring Ring It works like a Phone too: Ring Ring
**练习 10.9** [point_methods.go](exercises\chapter_10\point_methods.go) **练习 10.9** [point_methods.go](exercises/chapter_10/point_methods.go)
`point.go` 开始([第 10.1 节](10.1)的练习):使用方法来实现 `Abs()``Scale()`函数,`Point` 作为方法的接收者类型。也为 `Point3``Polar` 实现 `Abs()` 方法。完成了 `point.go` 中同样的事情,只是这次通过方法。 `point.go` 开始([第 10.1 节](10.1)的练习):使用方法来实现 `Abs()``Scale()`函数,`Point` 作为方法的接收者类型。也为 `Point3``Polar` 实现 `Abs()` 方法。完成了 `point.go` 中同样的事情,只是这次通过方法。
**练习 10.10** [inherit_methods.go](exercises\chapter_10\inherit_methods.go) **练习 10.10** [inherit_methods.go](exercises/chapter_10/inherit_methods.go)
定义一个结构体类型 `Base`,它包含一个字段 `id`,方法 `Id()` 返回 `id`,方法 `SetId()` 修改 `id`。结构体类型 `Person` 包含 `Base`,及 `FirstName``LastName` 字段。结构体类型 `Employee` 包含一个 `Person``salary` 字段。 定义一个结构体类型 `Base`,它包含一个字段 `id`,方法 `Id()` 返回 `id`,方法 `SetId()` 修改 `id`。结构体类型 `Person` 包含 `Base`,及 `FirstName``LastName` 字段。结构体类型 `Employee` 包含一个 `Person``salary` 字段。
创建一个 `employee` 实例,然后显示它的 `id` 创建一个 `employee` 实例,然后显示它的 `id`
**练习 10.11** [magic.go](exercises\chapter_10\magic.go) **练习 10.11** [magic.go](exercises/chapter_10/magic.go)
首先预测一下下面程序的结果,然后动手实验下: 首先预测一下下面程序的结果,然后动手实验下:

View File

@@ -58,7 +58,7 @@ func (t TT) String() string {
t.String() t.String()
``` ```
**练习 10.12** [type_string.go](exercises\chapter_10\type_string.go) **练习 10.12** [type_string.go](exercises/chapter_10/type_string.go)
给定结构体类型 `T`: 给定结构体类型 `T`:
@@ -72,19 +72,19 @@ type T struct {
`t`: `t := &T{7, -2.35, "abc\tdef"}`。给 T 定义 `String()`,使得 `fmt.Printf("%v\n", t)` 输出:`7 / -2.350000 / "abc\tdef"` `t`: `t := &T{7, -2.35, "abc\tdef"}`。给 T 定义 `String()`,使得 `fmt.Printf("%v\n", t)` 输出:`7 / -2.350000 / "abc\tdef"`
**练习 10.13** [celsius.go](exercises\chapter_10\celsius.go) **练习 10.13** [celsius.go](exercises/chapter_10/celsius.go)
`float64` 定义一个别名类型 `Celsius`,并给它定义 `String()`,它输出一个十进制数和 °C 表示的温度值。 `float64` 定义一个别名类型 `Celsius`,并给它定义 `String()`,它输出一个十进制数和 °C 表示的温度值。
**练习 10.14** [days.go](exercises\chapter_10\days.go) **练习 10.14** [days.go](exercises/chapter_10/days.go)
`int` 定义一个别名类型 `Day`,定义一个字符串数组它包含一周七天的名字,为类型 `Day` 定义 `String()` 方法,它输出星期几的名字。使用 `iota` 定义一个枚举常量用于表示一周的中每天MO、TU...)。 `int` 定义一个别名类型 `Day`,定义一个字符串数组它包含一周七天的名字,为类型 `Day` 定义 `String()` 方法,它输出星期几的名字。使用 `iota` 定义一个枚举常量用于表示一周的中每天MO、TU...)。
**练习 10.15** [timezones.go](exercises\chapter_10\timezones.go) **练习 10.15** [timezones.go](exercises/chapter_10/timezones.go)
`int` 定义别名类型 `TZ`,定义一些常量表示时区,比如 UTC定义一个 `map`,它将时区的缩写映射为它的全称,比如:`UTC -> "Universal Greenwich time"`。为类型 `TZ` 定义 `String()` 方法,它输出时区的全称。 `int` 定义别名类型 `TZ`,定义一些常量表示时区,比如 UTC定义一个 `map`,它将时区的缩写映射为它的全称,比如:`UTC -> "Universal Greenwich time"`。为类型 `TZ` 定义 `String()` 方法,它输出时区的全称。
**练习 10.16** [stack_arr.go](exercises\chapter_10\stack_arr.go) / [stack_struct.go](exercises\chapter_10\stack_struct.go) **练习 10.16** [stack_arr.go](exercises/chapter_10/stack_arr.go) / [stack_struct.go](exercises/chapter_10/stack_struct.go)
实现栈 (stack) 数据结构: 实现栈 (stack) 数据结构:
@@ -101,9 +101,9 @@ type T struct {
为栈定义一个 `Stack` 类型,并为它定义 `Push``Pop` 方法,再为它定义 `String()` 方法(用于调试)输出栈的内容,比如:`[0:i] [1:j] [2:k] [3:l]` 为栈定义一个 `Stack` 类型,并为它定义 `Push``Pop` 方法,再为它定义 `String()` 方法(用于调试)输出栈的内容,比如:`[0:i] [1:j] [2:k] [3:l]`
1[stack_arr.go](exercises\chapter_10\stack_arr.go):使用长度为 4 的 int 数组作为底层数据结构。 1[stack_arr.go](exercises/chapter_10/stack_arr.go):使用长度为 4 的 int 数组作为底层数据结构。
2 [stack_struct.go](exercises\chapter_10\stack_struct.go):使用包含一个索引和一个 `int` 数组的结构体作为底层数据结构,索引表示第一个空闲的位置。 2 [stack_struct.go](exercises/chapter_10/stack_struct.go):使用包含一个索引和一个 `int` 数组的结构体作为底层数据结构,索引表示第一个空闲的位置。
3使用常量 `LIMIT` 代替上面表示元素个数的 4 重新实现上面的 1和 2使它们更具有一般性。 3使用常量 `LIMIT` 代替上面表示元素个数的 4 重新实现上面的 1和 2使它们更具有一般性。

View File

@@ -26,9 +26,9 @@ runtime.SetFinalizer(obj, func(obj *typeObj))
在对象被 GC 进程选中并从内存中移除以前,`SetFinalizer` 都不会执行,即使程序正常结束或者发生错误。 在对象被 GC 进程选中并从内存中移除以前,`SetFinalizer` 都不会执行,即使程序正常结束或者发生错误。
**练习 10.17** [main_stack.go](exercises\chapter_10\main_stack.go) **练习 10.17** [main_stack.go](exercises/chapter_10/main_stack.go)
从练习 10.16 开始(它基于结构体实现了一个栈结构),为栈的实现 ([stack_struct.go](exercises\chapter_10\stack_struct.go)) 创建一个单独的包 `stack`,并从 `main``main.stack.go` 中调用它。 从练习 10.16 开始(它基于结构体实现了一个栈结构),为栈的实现 ([stack_struct.go](exercises/chapter_10/stack_struct.go)) 创建一个单独的包 `stack`,并从 `main``main.stack.go` 中调用它。
## 链接 ## 链接

View File

@@ -236,15 +236,15 @@ type Reader interface {
有的时候,也会以一种稍微不同的方式来使用接口这个词:从某个类型的角度来看,它的接口指的是:它的所有导出方法,只不过没有显式地为这些导出方法额外定一个接口而已。 有的时候,也会以一种稍微不同的方式来使用接口这个词:从某个类型的角度来看,它的接口指的是:它的所有导出方法,只不过没有显式地为这些导出方法额外定一个接口而已。
**练习 11.1** [simple_interface.go](exercises\chapter_11\simple_interface.go) **练习 11.1** [simple_interface.go](exercises/chapter_11/simple_interface.go)
定义一个接口 `Simpler`,它有一个 `Get()` 方法和一个 `Set()``Get()` 返回一个整型值,`Set()` 有一个整型参数。创建一个结构体类型 `Simple` 实现这个接口。 定义一个接口 `Simpler`,它有一个 `Get()` 方法和一个 `Set()``Get()` 返回一个整型值,`Set()` 有一个整型参数。创建一个结构体类型 `Simple` 实现这个接口。
接着定一个函数,它有一个 `Simpler` 类型的参数,调用参数的 `Get()``Set()` 方法。在 `main` 函数里调用这个函数,看看它是否可以正确运行。 接着定一个函数,它有一个 `Simpler` 类型的参数,调用参数的 `Get()``Set()` 方法。在 `main` 函数里调用这个函数,看看它是否可以正确运行。
**练习 11.2** [interfaces_poly2.go](exercises\chapter_11\interfaces_poly2.go) **练习 11.2** [interfaces_poly2.go](exercises/chapter_11/interfaces_poly2.go)
a) 扩展 [interfaces_poly.go](exercises\chapter_11\interfaces_poly.go) 中的例子,添加一个 `Circle` 类型 a) 扩展 [interfaces_poly.go](exercises/chapter_11/interfaces_poly.go) 中的例子,添加一个 `Circle` 类型
b) 使用一个抽象类型 `Shape`(没有字段) 实现同样的功能,它实现接口 `Shaper`,然后在其他类型里内嵌此类型。扩展 [10.6.5](10.6.md) 中的例子来说明覆写。 b) 使用一个抽象类型 `Shape`(没有字段) 实现同样的功能,它实现接口 `Shaper`,然后在其他类型里内嵌此类型。扩展 [10.6.5](10.6.md) 中的例子来说明覆写。

View File

@@ -274,7 +274,7 @@ type ReaderWriter struct {
**练习 11.11**[map_function_interface.go](exercises/chapter_11/map_function_interface.go) **练习 11.11**[map_function_interface.go](exercises/chapter_11/map_function_interface.go)
在练习 7.13 中我们定义了一个 `map()` 函数来使用 `int` 切片 ([map_function.go](exercises\chapter_7\map_function.go))。 在练习 7.13 中我们定义了一个 `map()` 函数来使用 `int` 切片 ([map_function.go](exercises/chapter_7/map_function.go))。
通过空接口和类型断言,现在我们可以写一个可以应用于许多类型的*泛型*的 `map()` 函数,为 `int``string` 构建一个把 `int` 值加倍和将字符串值与其自身连接(译者注:即 `"abc"` 变成 `"abcabc"` )的 `map()` 函数 `mapFunc()` 通过空接口和类型断言,现在我们可以写一个可以应用于许多类型的*泛型*的 `map()` 函数,为 `int``string` 构建一个把 `int` 值加倍和将字符串值与其自身连接(译者注:即 `"abc"` 变成 `"abcabc"` )的 `map()` 函数 `mapFunc()`

View File

@@ -66,7 +66,7 @@ func classifier(items ...interface{}) {
在示例 12.17 ([xml.go](examples/chapter_12/xml.go)) 中解析 XML 文档时,我们就会用到 `type-switch` 在示例 12.17 ([xml.go](examples/chapter_12/xml.go)) 中解析 XML 文档时,我们就会用到 `type-switch`
**练习 11.4** [simple_interface2.go](exercises\chapter_11\simple_interface2.go) **练习 11.4** [simple_interface2.go](exercises/chapter_11/simple_interface2.go)
接着练习 11.1 中的内容,创建第二个类型 `RSimple`,它也实现了接口 `Simpler`,写一个函数 `fi()`,使它可以区分 `Simple``RSimple` 类型的变量。 接着练习 11.1 中的内容,创建第二个类型 `RSimple`,它也实现了接口 `Simpler`,写一个函数 `fi()`,使它可以区分 `Simple``RSimple` 类型的变量。

View File

@@ -45,7 +45,7 @@ a := sort.IntArray(data) //conversion to type IntArray from package sort
sort.Sort(a) sort.Sort(a)
``` ```
完整的、可运行的代码可以在 [sort.go](examples\chapter_11\sort\sort.go) 和 [sortmain.go](examples\chapter_11\sortmain.go) 里找到。 完整的、可运行的代码可以在 [sort.go](examples/chapter_11/sort/sort.go) 和 [sortmain.go](examples/chapter_11/sortmain.go) 里找到。
同样的原理,排序函数可以用于一个浮点型数组,一个字符串数组,或者一个表示每周各天的结构体 `dayArray` 同样的原理,排序函数可以用于一个浮点型数组,一个字符串数组,或者一个表示每周各天的结构体 `dayArray`
@@ -194,17 +194,17 @@ type Interface interface {
这个接口总结了需要用于排序的抽象方法,函数 `Sort(data Interface)` 用来对此类对象进行排序,可以用它们来实现对其他类型的数据(非基本类型)进行排序。在上面的例子中,我们也是这么做的,不仅可以对 `int``string` 序列进行排序,也可以对用户自定义类型 `dayArray` 进行排序。 这个接口总结了需要用于排序的抽象方法,函数 `Sort(data Interface)` 用来对此类对象进行排序,可以用它们来实现对其他类型的数据(非基本类型)进行排序。在上面的例子中,我们也是这么做的,不仅可以对 `int``string` 序列进行排序,也可以对用户自定义类型 `dayArray` 进行排序。
**练习 11.5** [interfaces_ext.go](exercises\chapter_11\interfaces_ext.go) **练习 11.5** [interfaces_ext.go](exercises/chapter_11/interfaces_ext.go)
a). 继续扩展程序,定义类型 `Triangle`,让它实现 `AreaInterface` 接口。通过计算一个特定三角形的面积来进行测试(三角形面积=0.5 * (底 * 高) a). 继续扩展程序,定义类型 `Triangle`,让它实现 `AreaInterface` 接口。通过计算一个特定三角形的面积来进行测试(三角形面积=0.5 * (底 * 高)
b). 定义一个新接口 `PeriInterface`,它有一个 `Perimeter` 方法。让 `Square` 实现这个接口,并通过一个 `Square` 示例来测试它。 b). 定义一个新接口 `PeriInterface`,它有一个 `Perimeter` 方法。让 `Square` 实现这个接口,并通过一个 `Square` 示例来测试它。
**练习 11.6** [point_interfaces.go](exercises\chapter_11\point_interfaces.go) **练习 11.6** [point_interfaces.go](exercises/chapter_11/point_interfaces.go)
继续 [10.3](10.3.md) 中的练习 [point_methods.go](exercises\chapter_10\point_methods.go),定义接口 `Magnitude`,它有一个方法 `Abs()`。让 `Point``Point3``Polar` 实现此接口。通过接口类型变量使用方法做 point.go 中同样的事情。 继续 [10.3](10.3.md) 中的练习 [point_methods.go](exercises/chapter_10/point_methods.go),定义接口 `Magnitude`,它有一个方法 `Abs()`。让 `Point``Point3``Polar` 实现此接口。通过接口类型变量使用方法做 point.go 中同样的事情。
**练习 11.7** [float_sort.go](exercises\chapter_11\float_sort.go) / [float_sortmain.go](exercises\chapter_11\float_sortmain.go) **练习 11.7** [float_sort.go](exercises/chapter_11/float_sort.go) / [float_sortmain.go](exercises/chapter_11/float_sortmain.go)
类似 11.7 和示例 11.3/4定义一个包 `float64`,并在包里定义类型 `Float64Array`,然后让它实现 `Sorter` 接口用来对 `float64` 数组进行排序。 类似 11.7 和示例 11.3/4定义一个包 `float64`,并在包里定义类型 `Float64Array`,然后让它实现 `Sorter` 接口用来对 `float64` 数组进行排序。
@@ -216,7 +216,7 @@ b). 定义一个新接口 `PeriInterface`,它有一个 `Perimeter` 方法。
在主程序中新建一个此类型的变量,然后对它排序并进行测试。 在主程序中新建一个此类型的变量,然后对它排序并进行测试。
**练习 11.8** [sort.go](exercises\chapter_11\sort\sort.go) / [sort_persons.go](exercises\chapter_11\sort_persons.go) **练习 11.8** [sort.go](exercises/chapter_11/sort/sort.go) / [sort_persons.go](exercises/chapter_11/sort_persons.go)
定义一个结构体 `Person`,它有两个字段:`firstName``lastName`,为 `[]Person` 定义类型 `Persons` 。让 `Persons` 实现 `Sorter` 接口并进行测试。 定义一个结构体 `Person`,它有两个字段:`firstName``lastName`,为 `[]Person` 定义类型 `Persons` 。让 `Persons` 实现 `Sorter` 接口并进行测试。

View File

@@ -105,7 +105,7 @@ func main() {
any hello is a special String! any hello is a special String!
**练习 11.9** [simple_interface3.go](exercises\chapter_11\simple_interface3.go) **练习 11.9** [simple_interface3.go](exercises/chapter_11/simple_interface3.go)
继续练习 11.2,在它中添加一个 `gI()` 函数,它不再接受 `Simpler` 类型的参数,而是接受一个空接口参数。然后通过类型断言判断参数是否是 `Simpler` 类型。最后在 `main` 使用 `gI()` 取代 `fI()` 函数并调用它。确保你的代码足够安全。 继续练习 11.2,在它中添加一个 `gI()` 函数,它不再接受 `Simpler` 类型的参数,而是接受一个空接口参数。然后通过类型断言判断参数是否是 `Simpler` 类型。最后在 `main` 使用 `gI()` 取代 `fI()` 函数并调用它。确保你的代码足够安全。
@@ -141,7 +141,7 @@ func (p *Vector) Set(i int, e Element) {
`Vector` 中存储的所有元素都是 `Element` 类型要得到它们的原始类型unboxing拆箱需要用到类型断言。TODOThe compiler rejects assertions guaranteed to fail类型断言总是在运行时才执行因此它会产生运行时错误。 `Vector` 中存储的所有元素都是 `Element` 类型要得到它们的原始类型unboxing拆箱需要用到类型断言。TODOThe compiler rejects assertions guaranteed to fail类型断言总是在运行时才执行因此它会产生运行时错误。
**练习 11.10** [min_interface.go](exercises\chapter_11\min_interface.go) / [minmain.go](exercises\chapter_11\minmain.go) **练习 11.10** [min_interface.go](exercises/chapter_11/min_interface.go) / [minmain.go](exercises/chapter_11/minmain.go)
仿照 11.7 中开发的 `Sorter` 接口,创建一个 `Miner` 接口并实现一些必要的操作。函数 `Min()` 接受一个 `Miner` 类型变量的集合,然后计算并返回集合中最小的元素。 仿照 11.7 中开发的 `Sorter` 接口,创建一个 `Miner` 接口并实现一些必要的操作。函数 `Min()` 接受一个 `Miner` 类型变量的集合,然后计算并返回集合中最小的元素。