gopl-zh.github.com/ch2/ch2-06.md

3.9 KiB
Raw Blame History

2.6. 包和文件

Go语言中的包和其他语言的库或模块的概念类似目的都是为了支持模块化、封装、单独编译和代码重用。一个包的源代码保存在一个或多个以.go为文件后缀名的源文件中通常一个包所在目录路径的后缀是包的导入路径例如包gopl.io/ch1/helloworld对应的目录路径是$GOPATH/src/gopl.io/ch1/helloworld。

每个包都对应一个独立的名字空间。例如在image包中的Decode函数和在unicode/utf16包中的 Decode函数是不同的。要在外部引用该函数必须显式使用image.Decode或utf16.Decode形式访问。

包还可以让我们通过控制哪些名字是外部可见的来隐藏内部实现信息。在Go语言中一个简单的规则是如果一个名字是大写字母开头的那么该名字是导出的译注因为汉字不区分大小写因此汉字开头的名字是没有导出的

为了演示包基本的用法先假设我们的温度转换软件已经很流行我们希望到Go语言社区也能使用这个包。我们该如何做呢

让我们创建一个名为gopl.io/ch2/tempconv的包这是前面例子的一个改进版本。我们约定我们的例子都是以章节顺序来编号的这样的路径更容易阅读包代码存储在两个源文件中用来演示如何在一个源文件声明然后在其他的源文件访问虽然在现实中这样小的包一般只需要一个文件。

我们把变量的声明、对应的常量还有方法都放到tempconv.go源文件中

gopl.io/ch2/tempconv

// Package tempconv performs Celsius and Fahrenheit conversions.
package tempconv

import "fmt"

type Celsius float64
type Fahrenheit float64

const (
	AbsoluteZeroC Celsius = -273.15
	FreezingC     Celsius = 0
	BoilingC      Celsius = 100
)

func (c Celsius) String() string    { return fmt.Sprintf("%g°C", c) }
func (f Fahrenheit) String() string { return fmt.Sprintf("%g°F", f) }

转换函数则放在另一个conv.go源文件中

package tempconv

// CToF converts a Celsius temperature to Fahrenheit.
func CToF(c Celsius) Fahrenheit { return Fahrenheit(c*9/5 + 32) }

// FToC converts a Fahrenheit temperature to Celsius.
func FToC(f Fahrenheit) Celsius { return Celsius((f - 32) * 5 / 9) }

每个源文件都是以包的声明语句开始用来指名包的名字。当包被导入的时候包内的成员将通过类似tempconv.CToF的形式访问。而包级别的名字例如在一个文件声明的类型和常量在同一个包的其他源文件也是可以直接访问的就好像所有代码都在一个文件一样。要注意的是tempconv.go源文件导入了fmt包但是conv.go源文件并没有因为这个源文件中的代码并没有用到fmt包。

因为包级别的常量名都是以大写字母开头它们可以像tempconv.AbsoluteZeroC这样被外部代码访问

fmt.Printf("Brrrr! %v\n", tempconv.AbsoluteZeroC) // "Brrrr! -273.15°C"

要将摄氏温度转换为华氏温度需要先用import语句导入gopl.io/ch2/tempconv包然后就可以使用下面的代码进行转换了

fmt.Println(tempconv.CToF(tempconv.BoilingC)) // "212°F"

在每个源文件的包声明前仅跟着的注释是包注释§10.7.4。通常包注释的第一句应该先是包的功能概要说明。一个包通常只有一个源文件有包注释译注如果有多个包注释目前的文档工具会根据源文件名的先后顺序将它们链接为一个包注释。如果包注释很大通常会放到一个独立的doc.go文件中。

练习 2.1 向tempconv包添加类型、常量和函数用来处理Kelvin绝对温度的转换Kelvin 绝对零度是273.15°CKelvin绝对温度1K和摄氏度1°C的单位间隔是一样的。

{% include "./ch2-06-1.md" %}

{% include "./ch2-06-2.md" %}