From 3415aa002e462de8c1c34529811f510ca1411250 Mon Sep 17 00:00:00 2001 From: Unknwon Date: Fri, 7 Aug 2015 16:39:18 +0800 Subject: [PATCH] =?UTF-8?q?=E7=B2=BE=E6=A0=A1=EF=BC=9A9.5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README_gc.md | 2 +- TOC.md | 3 ++- eBook/09.5.md | 65 +++++++++++++++++++++++++-------------------------- 3 files changed, 35 insertions(+), 35 deletions(-) diff --git a/README_gc.md b/README_gc.md index 1545e12..9a28d88 100644 --- a/README_gc.md +++ b/README_gc.md @@ -19,4 +19,4 @@ Golang 编程:245386165 |更新日期 |更新内容 |----------|------------------ -|2015-08-06|9.4 精密计算和 big 包 \ No newline at end of file +|2015-08-07|9.5 自定义包和可见性 \ No newline at end of file diff --git a/TOC.md b/TOC.md index 58ee7d8..2b8268d 100644 --- a/TOC.md +++ b/TOC.md @@ -71,4 +71,5 @@ - 9.1 [标准库概述](eBook/09.1.md) - 9.2 [regexp 包](eBook/09.2.md) - 9.3 [锁和 sync 包](eBook/09.3.md) - - 9.4 [精密计算和 big 包](eBook/09.4.md) \ No newline at end of file + - 9.4 [精密计算和 big 包](eBook/09.4.md) + - 9.5 [自定义包和可见性](eBook/09.5.md) \ No newline at end of file diff --git a/eBook/09.5.md b/eBook/09.5.md index f60e0de..44cab7c 100755 --- a/eBook/09.5.md +++ b/eBook/09.5.md @@ -1,10 +1,10 @@ # 9.5 自定义包和可见性 -包是 Go 语言中代码组成和代码编译的主要方式。很多关于它们的基本信息已经在4.2章节中给出,最引人注目的便是可见性。现在我们来看看具体如何来使用自己写的包。在下一节,我们将回顾一些标准库中的包,自定义的包和标准库以外的包。 +包是 Go 语言中代码组成和代码编译的主要方式。很多关于它们的基本信息已经在 4.2 章节中给出,最引人注目的便是可见性。现在我们来看看具体如何来使用自己写的包。在下一节,我们将回顾一些标准库中的包,自定义的包和标准库以外的包。 -当写自己包的时候,要使用短小的不含有_(下划线)的小写单词来为文件命名。这里有个简单例子来说明包是如何相互调用以及可见性是如何实现的。 +当写自己包的时候,要使用短小的不含有 `_`(下划线)的小写单词来为文件命名。这里有个简单例子来说明包是如何相互调用以及可见性是如何实现的。 -当前目录下(examples/chapter9)有一个名为 package_test.go 的程序, 它使用了自定义包 pack1中pack1.go 的代码。这段程序(联通编译链接生成的pack1.a)存放在当前目录下一个名为 pack1 的文件夹下。所以链接器将包的对象和主程序对象链接在一起。 +当前目录下(examples/chapter9)有一个名为 package_test.go 的程序, 它使用了自定义包 pack1 中 pack1.go 的代码。这段程序(联通编译链接生成的 pack1.a)存放在当前目录下一个名为 pack1 的文件夹下。所以链接器将包的对象和主程序对象链接在一起。 示例 9.4 [pack1.go](examples/chapter_9/pack1.go): @@ -18,7 +18,7 @@ func ReturnStr() string { } ``` -它包含了一个整型变量 PackInt 和一个返回字符串的函数 ReturnStr。这段程序在运行时不做任何的事情,因为它不包含有一个 main 函数。 +它包含了一个整型变量 `PackInt` 和一个返回字符串的函数 `ReturnStr`。这段程序在运行时不做任何的事情,因为它不包含有一个 main 函数。 在主程序 pack_test.go 中这个包通过声明的方式被导入 @@ -28,7 +28,11 @@ import “./pack1/pack1” import 的一般格式如下: - import “包的路径或url地址“ 像 import "github.com/org1/pack1” + import "包的路径或 URL 地址" + +例如: + + import "github.com/org1/pack1” 路径是指当前目录的相对路径。 @@ -58,11 +62,17 @@ func main() { 如果包 pack1 和我们的程序在统同一路径下,我们可以通过 `"import ./pack1"` 这样的方式来引入,但这不被视为一个好的方法。 -`fmt.Printf(“Float from package1: %f\n”, pack1.pack1Float)` 这行代码试图访问一个未引用的变量或者函数,甚至没有编译。将会返回一个错误: +下面的代码试图访问一个未引用的变量或者函数,甚至没有编译。将会返回一个错误: +```go +fmt.Printf(“Float from package1: %f\n”, pack1.pack1Float) +``` + +错误: + cannot refer to unexported name pack1.pack1Float -主程序利用的包必须在主程序编写之前被编译。主程序中每个 pack1 项目都要通过包名来使用使用:pack1.Item。具体使用方法请参见示例 4.6 和 4.7。 +主程序利用的包必须在主程序编写之前被编译。主程序中每个 pack1 项目都要通过包名来使用使用:`pack1.Item`。具体使用方法请参见示例 4.6 和 4.7。 因此,按照惯例子目录和包之间有着密切的联系:为了区分不同包存放在不同的目录,每个包(所有属于这个包中的 go 文件)都存放在和包名相同的子目录下: @@ -78,23 +88,23 @@ pack1包只导入其副作用,也就是说,只执行它的init函数并初 **导入外部安装包:** -如果你要在你的应用中使用一个或多个外部包,首先你必须使用 go install(参见第 9.7 节)在你的本地机器上安装它们。 +如果你要在你的应用中使用一个或多个外部包,首先你必须使用 `go install`(参见第 9.7 节)在你的本地机器上安装它们。 -假设你想使用 http://codesite.ext/author/goExample/goex 这种托管在 googlecode, github,launchpad 等代码网站上的包。 +假设你想使用 `http://codesite.ext/author/goExample/goex` 这种托管在 Google Code、GitHub 和 Launchpad 等代码网站上的包。 你可以通过如下命令安装: go install codesite.ext/author/goExample/goex -将一个名为 codesite.ext/author/goExample/goex 的 map 安装在 `$GOROOT/src/` 目录下。 +将一个名为 `codesite.ext/author/goExample/goex` 的 map 安装在 `$GOROOT/src/` 目录下。 通过以下方式,一次性安装,并导入到你的代码中: import goex “codesite.ext/author/goExample/goex” -因此该包的URL将用作导入路径。 +因此该包的 URL 将用作导入路径。 -在 http://golang.org/cmd/goinstall/ 的 go install 文档中列出了一些广泛被使用的托管在网络代码仓库的包的导入路径 +在 `http://golang.org/cmd/goinstall/` 的 `go install` 文档中列出了一些广泛被使用的托管在网络代码仓库的包的导入路径 **包的初始化:** @@ -123,42 +133,31 @@ init 函数是不能被调用的。 然后终端执行 make 或 `gomake` 工具:他们都会生成一个包含静态库 pack1.a 的 _obj 目录。 -go install(参见第 9.7 节,从 Go1 的首选方式)同样复制 pack1.a 到本地的 $GOROOT/pkg 的目录中一个以操作系统为名的子目录下。像 import "pack1" 代替 import "path to pack1",这样只通过名字就可以将包在程序中导入。 - -如果不可取或不被允许,通过 6/8g 使用 -I 选项来编译: - - 6g—I map_pack1 package_test.go # where map_pack1 is the map which contains pack1.a - -(I 选项让编译器查找选项后的目录下是否包含这个包) - -使用 6/8l 的 -L 选项链接: - - 6l—L map_pack1 package_test.6 +go install(参见第 9.7 节,从 Go1 的首选方式)同样复制 pack1.a 到本地的 $GOROOT/pkg 的目录中一个以操作系统为名的子目录下。像 `import "pack1"` 代替 `import "path to pack1"`,这样只通过名字就可以将包在程序中导入。 当第 13 章我们遇到使用测试工具进行测试的时候我们将重新回到自己的包的制作和编译这个话题。 -练习: +**问题 9.1** -问题9.1: +a)一个包能分成多个源文件么? -(a)一个包能分成多个源文件么? +b)一个源文件是否能包含多个包? -(b)一个源文件是否能包含多个包? +**练习 9.3** -练习 9.3: 创建一个程序 main_greetings.go 能够和用户说 "Good Day" 或者 "Good Night"。不同的问候应该放到 greetings 包中。 -在同一个包中创建一个 ISAM 函数返回一个布尔值用来判断当前时间是 AM 还是 PM,同样创建 IsAfternoon 和 IsEvening 函数。 +在同一个包中创建一个 ISAM 函数返回一个布尔值用来判断当前时间是 AM 还是 PM,同样创建 `IsAfternoon` 和 `IsEvening` 函数。 使用 main_greetings 作出合适的问候(提示:使用 time 包)。 -练习 9.4:创建一个程序 main_oddven.go 判断前 100 个整数是不是偶数,包内同时包含测试的功能。 +**练习 9.4** 创建一个程序 main_oddven.go 判断前 100 个整数是不是偶数,包内同时包含测试的功能。 -练习 9.5:使用第 6.6 节的斐波那契程序: +**练习 9.5** 使用第 6.6 节的斐波那契程序: -(1)将斐波那契功能放入自己的 fibo 包中并通过主程序调用它,存储最后输入的值在函数的全局变量。 +1)将斐波那契功能放入自己的 fibo 包中并通过主程序调用它,存储最后输入的值在函数的全局变量。 -(2)扩展 fibo 包将通过调用斐波那契的时候,操作也作为一个参数。实验 "+" 和 “*” +2)扩展 fibo 包将通过调用斐波那契的时候,操作也作为一个参数。实验 "+" 和 “*” main_fibo.go / fibonacci.go