在 Go 语言里,包是个非常重要的概念。其设计理念是使用包来封装不同语义单元的功能,更好地复用代码,并对每个包内的数据的使用有更好的控制。

包的规则

  • 所有的.go 文件,除了空行和注释,都应该在第一行声明自己所属的包。
  • 每个包都在一个单独的目录里。
    • 不能把多个包放到同一个目录中,也不能把同一个包的文件分拆到多个不同目录中。
    • 这意味着,同一个目录下的所有.go 文件必须声明同一个包名。

包的命名

  • 给包命名的惯例是使用包所在目录的名字
  • 给包及其目录命名时,应该使用简洁、清晰且全小写的名字

记住:并不需要所有包的名字都与别的包不同,因为导入包时是使用全路径的,所以可以区分同名的不同包。一般情况下,包被导入后会使用你的包名作为默认的名字,不过这个导入后的名字可以修改。

main包

在 Go 语言里,命名为 main 的包具有特殊的含义。 Go 语言的编译程序会试图把这种名字的包编译为二进制可执行文件。所有用 Go 语言编译的可执行程序都必须有一个名叫 main 的包。

包的导入

导入包需要使用关键字import ,它会告诉编译器你想引用该位置的包内的代码。如果需要导入多个包,习惯上是将 import 语句包装在一个导入块中。

import (
	"fmt"
	"strings"
)

编译器查找packge的顺序:

  1. 标准库,如 /usr/local/go/src/*/*,这个路径由环境变量GOROOT决定。
  2. 当前项目源代码路径,如 /home/myproject/src/*/*
  3. gopath路径,如/home/sky/work/soft/go/*/*,这个路径由环境变量GOPATH决定。

查找策略:一旦编译器找到一个满足 import 语句的包,就停止进一步查找。

远程导入

Go 支持从远程网站获取源代码,如github:

import "github.com/spf13/viper"

获取过程使用 go get 命令完成

命名导入

重名的包可以通过命名导入来导入。

命名导入是指,在 import 语句给出的包路径的左侧定义一个名字,将导入的包命名为新名字。

import (
	"fmt"
	myfmt "mylib/fmt"
)

导入一个不在代码里使用的包时,Go 编译器会编译失败,输出错误。这个特性可以防止导入了未被使用的包,避免代码变得臃肿。

如果需要导入一个包,但是不需要引用这个包的标识符。在这种情况,可以使用空白标识符_ 来重命名这个导入:

import (
	_ "mylib/fmt"
)

init函数

每个包可以包含任意多个 init 函数,这些函数都会在程序执行开始的时候被调用。

多个init函数之间的执行顺序不定,不要依赖这个顺序。

所有被编译器发现的 init 函数都会安排在 main 函数之前执行。

init 函数用在设置包、初始化变量或者其他要在程序运行前优先完成的引导工作。