go package
包用于组织 Go 源代码以获得更好的可重用性和可读性。
包是位于同一目录中的 Go 源文件的集合。包提供了代码划分,因此很容易维护 Go 项目
包(package)是多个 Go 源码的集合,是一种高级的代码复用方案,像 fmt、os、io 等这样具有常用功能的内置包在 Go语言中有 150 个以上,它们被称为标准库,大部分(一些底层的除外)内置于 Go 本身。
包要求在同一个目录下的所有文件的第一行添加如下代码,以标记该文件归属的包:
package 包名
每个可执行的 Go 应用程序都必须包含 main 函数。该函数是执行的入口点。主要功能应该驻留在主包中。包的特性如下:
- 一个目录下的同级文件归属一个包。
- 包名可以与其目录不同名。
- 包名为 main 的包为应用程序的入口包,编译源码没有 main 包时,将无法编译输出可执行的文件。
当我们修改了一个源文件,我们必须重新编译该源文件对应的包和所有依赖该包的其他包。
即使是从头构建,Go语言编译器的编译速度也明显快于其它编译语言。Go语言的闪电般的编译速度主要得益于三个语言特性。
- 所有导入的包必须在每个文件的开头显式声明,这样的话编译器就没有必要读取和分析整个源文件来判断包的依赖关系。
- 禁止包的环状依赖,因为没有循环依赖,包的依赖关系形成一个有向无环图,每个包可以被独立编译,而且很可能是被并发编译。
- 编译后包的目标文件不仅仅记录包本身的导出信息,目标文件同时还记录了包的依赖关系。因此,在编译一个包的时候,编译器只需要读取每个直接导入包的目标文件,而不需要遍历所有依赖的的文件。
包标识符
如果想让一个包中的标识符(如变量、常量、类型、函数等)能被外部的包使用,那么标识符必须是对外可见的(public)。
在Go语言中是通过标识符的首字母大/小写来控制标识符的对外可见(public)/不可见(private)的。在一个包内部只有首字母大写的标识符才是对外可见的。
//包中的变量、类型、函数、方法,只有大写字母开头才能够被外部调用
type MyStruct struct {
// 包外可以访问的字段
ExportedField int
// 仅限包内访问的字段
privateField int
}
type MyInterface interface {
// 包外可以访问的方法
ExportedMethod()
// 仅限包内访问的方法
privateMethod()
}
空白表示符号
在 Go 中导入一个包并且不在代码中的任何地方使用它是非法的。
但是,当应用程序正在积极开发时导入包并在以后(如果不是现在)在代码中的某个地方使用它们是很常见的
有时我们需要导入一个包只是为了确保初始化发生,即使我们不需要使用包中的任何函数或变量
例如,我们可能需要确保调用包的init函数,packages/utils即使我们计划不在代码中的任何地方使用该包
在这种情况下也可以使用 _ 空白标识符
import (
"encoding/json"
"ginIMApi/models"
//"ginIMApi/packages/utils"
_ "ginIMApi/packages/utils"
"html"
"log"
"net/http"
"strconv"
"sync"
"time"
)
init初始化函数
在每一个Go源文件中,都可以定义任意个如下格式的特殊函数:
func init(){
// ...
}
这种特殊的函数不接收任何参数也没有任何返回值,我们也不能在代码中主动调用它。当程序启动的时候,init函数会按照它们声明的顺序自动执行。
一个包的初始化过程是按照代码中引入的顺序来进行的,所有在该包中声明的init函数都将被串行调用并且仅调用执行一次。
每一个包初始化的时候都是先执行依赖的包中声明的init函数再执行当前包中声明的init函数。确保在程序的main函数开始执行时所有的依赖包都已初始化完成。
- init 函数会在main 函数之前执行
- go 程序会更具导入包的顺序依次执行每一个包的init 函数