区块链基础语言(二十一)——Go语言包

在实际开发工作中,工程不会简单到只有一个源代码文件,且源文件之间有相互依赖的关系。Go语言利用命令行工具,消除了工程文件的概念,完全用目录结构和包名来推导工程结构和构建顺序。

一、包的由来

为了代码更好地维护和复用,Go语言程序按程序的功能性将源代码分割成一个个逻辑单元,组织成若干组文件,每组文件被称为一个包。这样开发人员可以以包为单位对代码进行维护;也可以以包为复用单元,引入到其他项目。

二、包名

为了方便包的定位,建议包名和目录名一致,即以.go为文件后缀名的源文件,其第一行代码所声明的包名和此文件所属的目录名一致。则同属一个路径下的每个以.go为文件后缀名的源文件的包名一致,都和目录名一致。

三、包的分类和导入

Go语言将包分为四类:main包、标准库包、程序内部包和第三方包。

3.1 main包

3.1.1 main包特点

用Go语言编译的可执行程序,其包名必须是main,而且这个main包里一定要有且仅有一个main()函数。如此,Go语言的编译程序会试图把main包编译为二进制的可执行文件,而main()函数就是这个程序的入口。

3.1.2 main函数

main()函数只能在main包里使用才是可执行函数,且main包有且仅有一个main()函数,main()函数在定义时不能有任何参数和返回值。main()函数是程序自动调用的,它是程序的执行起点。

3.1.3 init 函数i

nit()函数能够应用于所有的包,且每个包可以有任意多个init()函数,但为了程序的可读性和可维护性,建议每个文件最多只写一个init()函数。init()函数在定义时也不能有任何的参数和返回值。init ()函数是程序自动调用的,它在main()函数之前执行。在3.5中包的导入原理中再讲述main()函数和init()函数的执行顺序。

3.2 标准库包

Go程序在安装时就已经安装了Go语言标准库,内置于Go语言安装包下面的src包,它基本实现了Go语言常用功能。它的导入格式如下:

3.3 程序内部包

程序内部包,包括下载到本地的源码包和自定义代码包。Go语言规定下载到本地的源码包和自定义的代码包都要放在GOPATH的src目录下(或者GOPATH的src的某个子目录下)。在Go语言中,自定义代码包的代码文件名可以任意,但是这些文件都必须以包声明语句作为文件中的第一行(建议包名和目录名一致),每个包都对应一个独立的名字空间,例如一个文件的目录名为calc,其声明格式为:

通常一个包所在目录路径的后缀就是包的导入路径。根据路径是否相同,将不同的文件分为同一路径下的不同文件和不同路径下的不同文件。

3.3.1 同一路径下的不同文件

在Go语言程序里,同一路径下的多个文件被Go语言编译器看作是一个文件,程序里声明的包名必须相同(建议包名和目录名一致),可以直接相互引用数据(全局变量、函数、结构体、结构体成员),不用导入路径。因此,在这多个文件中不能出现相同的全局变量名、函数名、结构体类型名、结构体成员变量名,首字母大小写均不可以。需要注意,同一路径下,两个均声明为main包的文件可以相互访问对方的全局变量、函数、结构体、结构体成员,但是不能调用。因为一个可执行程序只能有一个main包,虽然两个文件均声明为main包,但不属于同一个程序。一般同一个路径声明为main包的文件只能有一个。

3.3.2 不同路径下的不同文件

不同路径下的文件,程序里声明的包名可以相同,也可以不同(根据实际开发需要而定)。但在执行程序中导入另一个文件中的数据,必须导入另一个文件所在的路径。假若所需要导入的函数sort.go所在路径为:

则在执行程序中写入此代码:

3.4 包的导入原理

如图1所示,程序的初始化和执行都起始于main包。如果main包还导入了其它的包,那么就会在编译时将它们依次导入。当一个包被导入时,如果该包还导入了其它的包,那么会先将其它包导入进来,然后再对这些包中的包级常量和变量进行初始化,接着执行init函数(如果有的话),依次类推。等所有被导入的包都加载完毕了,就会开始对main包中的包级常量和变量进行初始化,然后执行main包中的init函数(如果存在的话),最后执行main函数。包的导入过程如图1所示。

四、导入包的代码调用

导入包需要使用关键字import,即让编译器引入该位置的包内代码。包的路径可以是相对路径,也可以是绝对路径。

4.1 可见性规则

如果包内(main包除外)的全局变量名、函数名、结构体类型名、结构体成员变量名的首字母大写,则可以被外部包访问;如果首字母小写,只能被同一个包里的文件访问。

4.2 包中代码的调用

一个执行程序导入了包(标准库包、程序内部包、第三方包),未调用其中可被访问的对象(首字母大写的全局变量名、函数名、结构体变量名、结构体成员变量名),则编译错误。调用格式如表1所示。

包名为dcdfvfer的包路径为:
~/go/src/workSpace/dfv/dcdfvfer,dcdfvfer包导入main包的示例如下:

4.3 包的其他导入方法

包的其他导入方法包括:点操作、别名操作、下划线操作。

4.3.1 点操作

点操作,就是这个包导入之后,调用这个包的函数时可以省略前缀的包名。

4.3.2 别名操作

别名操作,就是包在导⼊时,对包重命名,调用包的函数时,前缀使用重命名之后的别名,不能使用原先本名。

4.3.3 操作

在4.2中已经介绍过,如果导入了包,则在程序中必须要调用该包里可以被访问的对象,否则编译出错。但有时候我们必须导入一个包,且仅仅利用它对包级别的变量执行初始化表达式求值,并执行init函数。这个时候可以使用空白标识符_来重命名这个导入:

参考资料
[1] 许式伟,吕桂华.Go语言编程[M].北京:人民邮电出版社,2012:13.
[2] 

posted @ 2019-03-07 15:01  网鱼  阅读(268)  评论(0编辑  收藏  举报