基本概念
- 源码文件的第一行有效代码必须是
package pacakgeName
语句,通过该语句声明自己所在的包
- 一般包的名称就是其源文件
所在目录的名称
,虽然Go语言没有强制要求包名必须和其所在的目录名同名,但还是建议包名和所在目录同名,这样结构更清晰
- 包可以定义在很深的目录中,包名的定义是不包括目录路径的,但是包在引用时一般使用全路径引用。比如在
GOPATH/src/a/b/
下定义一个包 c
。在包 c
的源码中只需声明为package c
,而不是声明为package a/b/c
,但是在导入 c
包时,需要带上路径,例如import "a/b/c"
- 包名一般是小写的,使用一个简短且有意义的名称
- 包名一般要和所在的目录同名,也可以不同,包名中不能包含
-
等特殊符号
- 包一般使用域名作为目录名称,这样能保证包名的唯一性,比如 GitHub 项目的包一般会放到
GOPATH/src/github.com/userName/projectName
目录下
- 包名为
main
的包为应用程序的入口包,编译不包含 main
包的源码文件时不会得到可执行文件
- 一个文件夹下的所有源码文件只能属于同一个包,同样属于同一个包的源码文件不能放在多个文件夹下
包的导入
- import 导入语句通常放在源码文件开头包声明语句的下面
- 导入的包名需要使用双引号包裹起来
- 包名是从
GOPATH/src/
后开始计算的,使用 /
进行路径分隔
- 包的引用路径有两种写法,分别是全路径导入和相对路径导入,相对路径只能用于导入
GOPATH
下的包,标准包的导入只能使用全路径导入
包的引用格式
- 标准引用格式
package main
import "fmt"
func main() {
fmt.Println("Hello world")
}
- 自定义别名引用格式
package main
import F "fmt"
func main() {
F.Println("Hello world")
}
- 省略引用格式
package main
import . "fmt"
func main() {
Println("Hello world")
}
- 匿名引用格式
package main
import (
_ "database/sql"
"fmt"
)
func main() {
fmt.Println("Hello world")
}
包加载
- 包初始化程序从 main 函数引用的包开始,逐级查找包的引用,直到找到没有引用其他包的包,最终生成一个包引用的有向无环图
- Go 编译器会将有向无环图转换为一棵树,然后从树的叶子节点开始逐层向上对包进行初始化
- 单个包的初始化过程如上图所示,先初始化常量,然后是全局变量,最后执行包的 init 函数