定义包
一个包可以简单理解为一个存放.go
文件的文件夹。这些go
文件都归属于该包,通过在代码第一行声明实现。声明格式:
package 包名
注意:
- 一个包下面的所有文件只能归属于同一个包。
- 包名可以和文件夹名不同,包名不能包含
-
符号。 main
包是应用程序的入口包,只有main
包才会在编译后生成可执行文件。
包中标识符的对外可见性
标识符包括变量、常量、类型、函数等,还有结构体中的字段名、接口中的方法名,Go语言中只要将标识符的首字母大写,就可以让该标识符对外可见。
导入包
使用import
关键字导入需要使用的包。
import "包名"
注意:
- 导入语句通常放在包声明语句的下面。
- 导入的包名需要用双引号包裹。
- 对于自定义的包,导入时需要加路径。(如果设置了GOPATH,包名是从
$GOPATH/src/
后开始计算的,使用/
进行路径分隔) - 禁止循环导入包
单行导入
import "包1"
import "包2"
多行导入
import (
"包1"
"包2"
)
导入时自定义包名
导入包时可以自定义别名,通常用于包名太长(带路径时名字往往很长)或包名冲突时。
用法:
import 别名 "包名"
当不需要使用包中的数据时,可以匿名导入(比如只需要执行包中的init()函数
):
import _ "包名"
init()初始化函数
在Go语言程序执行时导入包语句会自动触发包内部init()
函数的调用。需要注意的是: init()
函数没有参数也没有返回值。 init()
函数在程序运行时自动被调用执行,不能在代码中主动调用它。
示例:
package main
import (
"fmt"
)
func init() {
fmt.Println("自动执行")
}
func main() {
fmt.Println("先执行init()函数")
}
输出:
自动执行
先执行init()函数
包中init()函数执行时机
全局声明->init()
函数->main()
函数
所有init()函数执行顺序
程序编译时,从main
包开始检查导入的包,其中导入的包中可能还导入了其它包。最终可以构建树状的包引用关系,再根据引用顺序决定编译顺序,依次编译这些包的代码。运行时,最后导入的包最先初始化并调用其init()
函数。
简单实例
自定义一个calc
包:
package calc
import "fmt"
// init()函数可以不写,这里是为了体现其执行顺序
func init() {
fmt.Println("执行calc包的init()函数")
}
// Add 两数求和
func Add(x, y int) int {
return x + y
}
calc
包中Add()
函数首字母大写,使其对其它包可见。
然后在main
包中导入calc
包:
package main
import (
"fmt"
calc "xxxx/xxx/xxx/xxx/03calc" // 使用别名
)
// init()函数可以不写,这里是为了体现其执行顺序
func init() {
fmt.Println("执行main包的init()函数")
}
func main() {
fmt.Println(calc.Add(2, 3))
}
calc
包文件在文件夹"03calc"下,如果文件夹名和包名相同,可以不取别名,否则需要取别名,别名可以和包名相同。
输出:
执行calc包的init()函数
执行main包的init()函数
5
可以看到,calc
包后导入,其init()
函数先执行。