go 语言包
在一个项目中通常我们需要引入第三方包,我们来看下 当我们导入一个包的时候 发生了什么:
首先我们先详细介绍下两个函数: init(), main() 是 go 语言中的保留函数。我们可以在源码中 定义 init()函数, 此函数会在包导入时执行, 例如 如果是在 main 中导入包,包中存在 init(), 那么 init() 中的代码会在 main() 函数执行前执行。 用于初始化包 所需要的特定材料。 例如:
包代码:
src/userPackage/tool.gopackage userpackage import "fmt" func init(){fmt.Println("tool init") }
主函数代码:
src/main.gopackage main import ("userPackage" )func main(){fmt.Pintln("main run")// 使用 userPackageuserPackage.SomeFunc() }
他们在执行时: 会先输出: "tool init" 在输出 "main run"
init() 函数和 main() 这两个函数的区别:
相同点:
- 这两个函数都是 go 语言中的保留函数
- 两个函数在定义是不能有 任何参数 和 返回值
- 该函数只能由 go 程序自动调用, 不能被引用(自己调用)
不同点:
- init 可以应用于任意包中,且可以重复定义多个
- main 函数只能用于 main 包中,切只能定义一个
- init 主要用于初始化信息的
- main 程序入口
init() 函数和 main() 函数执行顺序:
- 在 main 包中的 go 文件默认总是会被执行。
- 对用同一个 go 文件 的 init() 调用顺序是从上到下的
package utils import "fmt" func init() {fmt.Println("util init0") } func init() {fmt.Println("util init1") }输出: util init0 util init1
- 对同一个 package 中的不同文件 将文件名安装字符串进行 "从大到小" 排序,之后顺序调用各个文件中的 init 函数
package utils import "fmt" func init() {fmt.Println("util init0") } func init() {fmt.Println("util init1") }package utils import "fmt" func init() {fmt.Println("utilTime init0") }输出: util init0 util init1 utilTime init0
- 对于不同的 package, 如果不互相依赖 按照 main 包中 import 的顺序调用其他包中的 init() 函数。
package main import ("fmt"_ "practice_package/utils" ) func init() {fmt.Println("main init") } func main() {fmt.Println("main main->run") }输出: util init0 util init1 utilTime init0 main init main main->run
- 对于不同的 package, 如果相互依赖 调用顺序为 顺序为最后被依赖的 最先进行初始化。例如: 导入顺序: main ->A ->B ->C, 则 初始化顺序为 C->B->A->mian, 依次执行对应的 init 方法。main 包总是被最后一个初始化。应为它总是 依赖别的包
- 避免出现循环导入 例如: A->B->C->A;(虽然实际生产不可避免,但还是得尽量避免)
- 一个包被多个包 import, init() 函数只会执行一次