非零基础自学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函数。