非零基础自学Golang
第8章 包管理
8.4 main包
在Go语言中,命名为main的包具有特殊的含义。Go语言的编译程序会试图把这种名字的包编译为二进制可执行文件。
所有用Go语言编译的可执行程序都必须有一个名叫main的包,main包有且仅有一个。
当编译器发现某个包的名字为main时,它一定也会发现名为main()的函数,否则不会创建可执行文件。
main()函数是程序的入口,所以,如果没有这个函数,程序就没有办法开始执行。程序编译时,会使用声明main包的代码所在的目录名称作为可执行文件的文件名。
一个应用程序可以包含不同的包,而且即使你只使用main包也不必把所有的代码都写在一个巨大的文件里,你可以用一些较小的文件,并且在每个文件非注释的第一行都使用package main来指明这些文件都属于main包。如果你打算编译包名不为main的源文件,如mypack,编译后产生的对象文件将会是mypack.a而不是可执行程序。
【嗦嘎!!!】
另外要注意的是,所有的包名都应该使用小写字母。【OK】
8.5 包的初始化
在Go语言里面有两个保留的函数:
- init函数(能够应用于所有的package)
- main函数(只能应用于package main)。
这两个函数在定义时不能有任何的参数和返回值。虽然一个package里面可以写任意多个init函数,但无论是对于可读性还是以后的可维护性来说,我们都强烈建议用户在一个package中,每个文件只写一个init函数。
我们导入了一个包就可以使用该包中的常量和变量,当然这些常量和变量必须是可导出的。
package main
import (
"fmt"
"time"
)
func main() {
fmt.Printf("time 包中的常量Second: %v \n", time.Second)
fmt.Printf("time 包中的UTC常量: %v \n", time.UTC)
time.UTC, _ = time.LoadLocation("Local")
fmt.Printf("time 包中的UTC 变量更改后的值: %v \n", time.UTC)
}
运行结果

动手写8.5.1导入了time包,使用了time包的Second常量和UTC变量
Go程序会自动调用init()和main(),所以你不需要在任何地方调用这两个函数。每个package中的init函数都是可选的,但package main就必须包含一个main函数。
每个包可以包含任意多个init(),这些函数都会在程序执行开始的时候被调用。所有被编译器发现的init()都会安排在main()之前执行。
init()用于设置包、初始化变量或者其他要在程序运行前优先完成的引导工作。
程序的初始化和执行都起始于main包。
如果main包还导入了其他的包,那么就会在编译时将它们依次导入。
有时一个包会被多个包同时导入,但它只会被导入一次(例如很多包可能都会用到fmt包,但它只会被导入一次,因为没有必要导入多次)。
当一个包被导入时,如果该包还导入了其他的包,那么会先将其他的包导入进来,然后再对该包的包级常量和变量进行初始化,最后执行init函数(如果存在)。包的导入如图8.5.1所示,

是一个递归的过程,等所有被导入的包加载完毕,就会对main包中的包级常量和变量进行初始化,然后执行main包中的init函数(如果存在),最后执行main函数。