精校:9.5

This commit is contained in:
Unknwon
2015-08-07 16:39:18 +08:00
parent eced2ba1b2
commit 3415aa002e
3 changed files with 35 additions and 35 deletions

View File

@@ -19,4 +19,4 @@ Golang 编程245386165
|更新日期 |更新内容 |更新日期 |更新内容
|----------|------------------ |----------|------------------
|2015-08-06|9.4 精密计算和 big 包 |2015-08-07|9.5 自定义包和可见性

3
TOC.md
View File

@@ -71,4 +71,5 @@
- 9.1 [标准库概述](eBook/09.1.md) - 9.1 [标准库概述](eBook/09.1.md)
- 9.2 [regexp 包](eBook/09.2.md) - 9.2 [regexp 包](eBook/09.2.md)
- 9.3 [锁和 sync 包](eBook/09.3.md) - 9.3 [锁和 sync 包](eBook/09.3.md)
- 9.4 [精密计算和 big 包](eBook/09.4.md) - 9.4 [精密计算和 big 包](eBook/09.4.md)
- 9.5 [自定义包和可见性](eBook/09.5.md)

View File

@@ -1,10 +1,10 @@
# 9.5 自定义包和可见性 # 9.5 自定义包和可见性
包是 Go 语言中代码组成和代码编译的主要方式。很多关于它们的基本信息已经在4.2章节中给出,最引人注目的便是可见性。现在我们来看看具体如何来使用自己写的包。在下一节,我们将回顾一些标准库中的包,自定义的包和标准库以外的包。 包是 Go 语言中代码组成和代码编译的主要方式。很多关于它们的基本信息已经在 4.2 章节中给出,最引人注目的便是可见性。现在我们来看看具体如何来使用自己写的包。在下一节,我们将回顾一些标准库中的包,自定义的包和标准库以外的包。
当写自己包的时候,要使用短小的不含有_(下划线)的小写单词来为文件命名。这里有个简单例子来说明包是如何相互调用以及可见性是如何实现的。 当写自己包的时候,要使用短小的不含有 `_`(下划线)的小写单词来为文件命名。这里有个简单例子来说明包是如何相互调用以及可见性是如何实现的。
当前目录下(examples/chapter9)有一个名为 package_test.go 的程序, 它使用了自定义包 pack1pack1.go 的代码。这段程序(联通编译链接生成的pack1.a)存放在当前目录下一个名为 pack1 的文件夹下。所以链接器将包的对象和主程序对象链接在一起。 当前目录下examples/chapter9有一个名为 package_test.go 的程序, 它使用了自定义包 pack1pack1.go 的代码。这段程序(联通编译链接生成的 pack1.a)存放在当前目录下一个名为 pack1 的文件夹下。所以链接器将包的对象和主程序对象链接在一起。
示例 9.4 [pack1.go](examples/chapter_9/pack1.go) 示例 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 中这个包通过声明的方式被导入 在主程序 pack_test.go 中这个包通过声明的方式被导入
@@ -28,7 +28,11 @@ import “./pack1/pack1”
import 的一般格式如下: import 的一般格式如下:
import 包的路径或url地址“ 像 import "github.com/org1/pack1” import "包的路径或 URL 地址"
例如:
import "github.com/org1/pack1”
路径是指当前目录的相对路径。 路径是指当前目录的相对路径。
@@ -58,11 +62,17 @@ func main() {
如果包 pack1 和我们的程序在统同一路径下,我们可以通过 `"import ./pack1"` 这样的方式来引入,但这不被视为一个好的方法。 如果包 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 cannot refer to unexported name pack1.pack1Float
主程序利用的包必须在主程序编写之前被编译。主程序中每个 pack1 项目都要通过包名来使用使用pack1.Item。具体使用方法请参见示例 4.6 和 4.7。 主程序利用的包必须在主程序编写之前被编译。主程序中每个 pack1 项目都要通过包名来使用使用:`pack1.Item`。具体使用方法请参见示例 4.6 和 4.7。
因此,按照惯例子目录和包之间有着密切的联系:为了区分不同包存放在不同的目录,每个包(所有属于这个包中的 go 文件)都存放在和包名相同的子目录下: 因此,按照惯例子目录和包之间有着密切的联系:为了区分不同包存放在不同的目录,每个包(所有属于这个包中的 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 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” 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 目录。 然后终端执行 make 或 `gomake` 工具:他们都会生成一个包含静态库 pack1.a 的 _obj 目录。
go install(参见第 9.7 节,从 Go1 的首选方式)同样复制 pack1.a 到本地的 $GOROOT/pkg 的目录中一个以操作系统为名的子目录下。像 import "pack1" 代替 import "path to pack1",这样只通过名字就可以将包在程序中导入。 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
当第 13 章我们遇到使用测试工具进行测试的时候我们将重新回到自己的包的制作和编译这个话题。 当第 13 章我们遇到使用测试工具进行测试的时候我们将重新回到自己的包的制作和编译这个话题。
练习: **问题 9.1**
问题9.1: a一个包能分成多个源文件么
(a)一个包能分成多个源文件么 b一个源文件是否能包含多个包
(b)一个源文件是否能包含多个包? **练习 9.3**
练习 9.3
创建一个程序 main_greetings.go 能够和用户说 "Good Day" 或者 "Good Night"。不同的问候应该放到 greetings 包中。 创建一个程序 main_greetings.go 能够和用户说 "Good Day" 或者 "Good Night"。不同的问候应该放到 greetings 包中。
在同一个包中创建一个 ISAM 函数返回一个布尔值用来判断当前时间是 AM 还是 PM同样创建 IsAfternoon 和 IsEvening 函数。 在同一个包中创建一个 ISAM 函数返回一个布尔值用来判断当前时间是 AM 还是 PM同样创建 `IsAfternoon``IsEvening` 函数。
使用 main_greetings 作出合适的问候(提示:使用 time 包)。 使用 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 main_fibo.go / fibonacci.go