Go程序设计语言2.6 包和文件

简介:

2.6 包和文件


在Go语言中包的作用和其他语言中的库或模块作用类似,用于支持模块化、封装、编译隔离和重用。一个包的源代码保存在一个或多个以.go结尾的文件中,它所在目录名的尾部就是包的导入路径,例如,gopl.io/ch1/helloworld包的文件存储在目录$GOPATH/src/gopl.io/ch1/helloworld中。

每一个包给它的声明提供独立的命名空间。例如,在image包中,Decode标识符和unicode/utf16包中的标识符一样,但是关联了不同的函数。为了从包外部引用一个函数,我们必须明确修饰标识符来指明所指的是image.Decode或utf16.Decode。

包让我们可以通过控制变量在包外面的可见性或导出情况来隐藏信息。在Go里,通过一条简单的规则来管理标识符是否对外可见:导出的标识符以大写字母开头。

为了说明基本原理,假设温度转换软件很受欢迎,我们想把它作为新包贡献给Go社区,将要怎么做呢?

我们创建一个叫作gopl.io/ch2/tempconv的包,这是前面例子的变种(这里我们没有照惯例对例子进行顺序编号,目的是让包路径更实际一些)。包自己保存在两个文件里,以展示如何访问一个包里面多个独立文件中的声明。现实中,像这样的小包可能只需要一个文件。

将类型、它们的常量及方法的声明放在tempconv.go中:

 

 

将转换函数放在conv.go中:

 

每一个文件的开头用package声明定义包的名称。当导入包时,它的成员通过诸如tempconv.CToF等方式被引用。如果包级别的名字(像类型和常量)在包的一个文件中声明,就像所有的源代码在同一个文件中一样,它们对于同一个包中的其他文件可见。注意,tempconv.go导入fmt包,但是conv.go没有,因为它本身没有用到fmt包。

因为包级别的常量名字以大写字母开头,所以它们也可以使用修饰过的名称(如tempconv.AbsoluteZeroC)来访问:

 

为了在某个包里将摄氏温度转换为华氏温度,导入包gopl.io/ch2/tempconv,然后编写下面的代码:

 

package声明前面紧挨着的文档注释(参考10.7.4节)对整个包进行描述。习惯上,应该在开头用一句话对包进行总结性的描述。每一个包里只有一个文件应该包含该包的文档注释。扩展的文档注释通常放在一个文件中,按惯例名字叫作doc.go。

练习2.1:添加类型、常量和函数到tempconv包中,处理以开尔文为单位(K)的温度值,0K=-273.15℃,变化1K和变化1℃是等价的。

2.6.1 导入

在Go程序里,每一个包通过称为导入路径(import path)的唯一字符串来标识。它们出现在诸如"gopl.io/ch2/tempconv"之类的import声明中。语言的规范没有定义哪些字符串从哪来以及它们的含义,这依赖于工具来解释。当使用go工具(参考第10章)时,一个导入路径标注一个目录,目录中包含构成包的一个或多个Go源文件。除了导入路径之外,每个包还有一个包名,它以短名字的形式(且不必是唯一的)出现在包的声明中。按约定,包名匹配导入路径的最后一段,这样可以方便地预测gopl.io/ch2/tempconv的包名是tempconv。

为了使用gopl.io/ch2/tempconv,必须导入它:

 

导入声明可以给导入的包绑定一个短名字,用来在整个文件中引用包的内容。上面的import可以使用修饰标识符来引用gopl.io/ch2/tempconv包里的变量名,如tempconv.CToF。默认这个短名字是包名,在本例中是tempconv,但是导入声明可以设定一个可选的名字来避免冲突(参考10.4节)。

cf程序将一个数字型的命令行参数分别转换成摄氏温度和华氏温度:

 

如果导入一个没有被引用的包,就会触发一个错误。这个检查帮助消除代码演进过程中不再需要的依赖(尽管它在调试过程中会带来一些麻烦),因为注释掉一条诸如log.Print("got here!")之类的代码,可能去除了对于log包唯一的一个引用,导致编译器报错。这种情况下,需要注释掉或者删掉不必要的import。

练习2.2:写一个类似于cf的通用的单位转换程序,从命令行参数或者标准输入(如果没有参数)获取数字,然后将每一个数字转换为以摄氏温度和华氏温度表示的温度,以英寸和米表示的长度单位,以磅和千克表示的重量,等等。

2.6.2 包初始化

包的初始化从初始化包级别的变量开始,这些变量按照声明顺序初始化,在依赖已解析完毕的情况下,根据依赖的顺序进行。

 

如果包由多个.go文件组成,初始化按照编译器收到文件的顺序进行:go工具会在调用编译器前将.go文件进行排序。

对于包级别的每一个变量,生命周期从其值被初始化开始,但是对于其他一些变量,比如数据表,初始化表达式不是简单地设置它的初始化值。这种情况下,init函数的机制会比较简单。任何文件可以包含任意数量的声明如下的函数:

 

这个init函数不能被调用和被引用,另一方面,它也是普通的函数。在每一个文件里,当程序启动的时候,init函数按照它们声明的顺序自动执行。

包的初始化按照在程序中导入的顺序来进行,依赖顺序优先,每次初始化一个包。因此,如果包p导入了包q,可以确保q在p之前已完全初始化。初始化过程是自下向上的,main包最后初始化。在这种方式下,在程序的main函数开始执行前,所有的包已初始化完毕。

下面的包定义了一个PopCount函数,它返回一个数字中被置位的个数,即在一个uint64的值中,值为1的位的个数,这称为种群统计。它使用init函数来针对每一个可能的8位值预计算一个结果表pc,这样PopCount只需要将8个快查表的结果相加而不用进行64步的计算。(这个不是最快的统计位算法,只是方便用来说明init函数,用来展示如何预计算一个数值表,它是一种很有用的编程技术。)

 

注意,init中的range循环只使用索引;值不是必需的,所以没必要包含进来。循环可以重写为下面的形式:

 

我们将在下一节和10.5节看到init函数的其他用途。

练习2.3:使用循环重写PopCount来代替单个表达式。对比两个版本的效率。(11.4节会展示如何系统性地对比不同实现的性能。)

练习2.4:写一个用于统计位的PopCount,它在其实际参数的64位上执行移位操作,每次判断最右边的位,进而实现统计功能。把它与快查表版本的性能进行对比。

练习2.5:使用x&(x-1)可以清除x最右边的非零位,利用该特点写一个PopCount,然后评价它的性能。

相关文章
|
3天前
|
编译器 Go 开发者
go语言中导入相关包
【11月更文挑战第1天】
13 3
|
7天前
|
Unix Linux Go
go进阶编程:Golang中的文件与文件夹操作指南
本文详细介绍了Golang中文件与文件夹的基本操作,包括读取、写入、创建、删除和遍历等。通过示例代码展示了如何使用`os`和`io/ioutil`包进行文件操作,并强调了错误处理、权限控制和路径问题的重要性。适合初学者和有经验的开发者参考。
|
9天前
|
算法 大数据 Go
Go文件操作:掌握Go的文件读写与操作技巧
本文介绍了Go语言的文件操作功能,包括文件的打开、读写和关闭。Go语言通过`os`和`io`包提供了丰富的文件操作接口,使开发者能够轻松实现文件的读写和管理。文章详细讲解了核心概念、具体操作步骤和代码示例,并探讨了实际应用场景和未来发展趋势。
|
9天前
|
存储 前端开发 Go
Go 文件的读取操作
本文介绍了 Go 语言标准库中的 `os` 包和 `bufio` 包,重点讲解了 `os` 包中的 `Open` 和 `OpenFile` 函数及 `File` 结构体的 `Read` 方法,以及 `bufio` 包中的 `NewReader` 函数和 `Reader` 结构体的 `ReadString` 方法。通过示例代码展示了如何使用这些方法高效读取文件,减少磁盘操作。
|
1月前
|
存储 Go 文件存储
M.2移动硬盘打造Win To Go系统:高效分区存储文件全攻略
【10月更文挑战第12天】本文详细介绍了如何使用M.2移动硬盘制作Win To Go系统。首先,需准备合适容量与接口类型的M.2硬盘及硬盘盒,并获取Windows镜像文件和分区工具。接着,通过Rufus软件将镜像写入硬盘。文中还提供了分区策略,包括系统分区(约80-120GB)、软件分区(根据需求设定)和数据分区(剩余空间),并指导如何使用DiskGenius或Windows自带工具进行分区。最后,强调了对各分区文件的有效管理和定期备份的重要性。
|
1月前
|
存储 固态存储 Go
M.2移动硬盘打造Win To Go系统:高效分区存储文件全攻略
【10月更文挑战第11天】Win To Go 是一种将 Windows 系统安装在 M.2 移动硬盘上的技术,便于用户携带自定义系统跨设备使用。需准备高性能 M.2 硬盘及合适硬盘盒,并使用 DiskGenius 或 Rufus 进行分区与系统安装。系统分区用于安装 Windows,其余分区可根据需求存储工作或娱乐文件,便于管理和备份。
109 2
|
23天前
|
存储 Go 数据库
Go语言Context包源码学习
【10月更文挑战第21天】Go 语言中的 `context` 包用于在函数调用链中传递请求上下文信息,支持请求的取消、超时和截止时间管理。其核心接口 `Context` 定义了 `Deadline`、`Done`、`Err` 和 `Value` 方法,分别用于处理截止时间、取消信号、错误信息和键值对数据。包内提供了 `emptyCtx`、`cancelCtx`、`timerCtx` 和 `valueCtx` 四种实现类型,满足不同场景需求。示例代码展示了如何使用带有超时功能的上下文进行任务管理和取消。
|
2月前
|
存储 Go
Golang语言基于go module方式管理包(package)
这篇文章详细介绍了Golang语言中基于go module方式管理包(package)的方法,包括Go Modules的发展历史、go module的介绍、常用命令和操作步骤,并通过代码示例展示了如何初始化项目、引入第三方包、组织代码结构以及运行测试。
43 3
|
3月前
|
编译器 数据库连接 Go
Go Sync 包:并发的 6 个关键概念
Go Sync 包:并发的 6 个关键概念
|
3月前
|
Go 开发者
下一篇
无影云桌面