【Go】Go程序的执行顺序
大家好 我是寸铁👊
总结了一篇Go程序的执行顺序的文章✨
喜欢的小伙伴可以点点关注 💝
Go程序内容
go程序通常包含: 包、常量、变量、init()、main()等元素
下面从这几个方面分别去梳理!
包的执行顺序
程序中的包
- 一个.go文件中,其他的包只有被
main
包import才会执行,按照import的先后
顺序执行。 - 被
依赖
的包的初始化顺序与其import
顺序相反,或者说按照**"深度优先"**的顺序执行例如:导入顺序为main->A->B->C
,则初始化顺序为C->B->A->main
, 如下图所示: - 避免出现
循环import
,例如: A --> B --> C -->A
- main包总是被最后一个初始化,因为它总是依赖别的包。
- 一个包被其他多个包依赖的包,只会初始化一次。
包的内部
- 每个包内部按照
常量=>变量=>init()
函数的顺序进行初始化 - 包内的
init()
函数按照出现次序自动调用
import、常量、变量、init()、main()
在同一个go文件中,import
、常量
、变量
、init()
、main()
依次进行初始化。
要了解init
函数和main
函数的执行顺序,先要熟悉这两个函数的特点
init和main函数的特点
init()、main()
是go语言中的保留函数
init函数的特点:
- init函数
先于main函数自动执行
,不能
被其他函数调用; - init函数
没有输入参数、返回值
; - 每个包可以有
多个
init函数; - 包的每个原文件也可以有多个init函数,这点比较特殊;
同一个包
的init执行顺序,golang没有明确定义。- 不同包的
init
函数按照包导入的依赖关系
决定执行顺序
。
init和main函数的的区别:
相同点
- 两个函数在定义时
不能有任何的参数和返回值
- 该函数只能由
go程序
自动调用,不可以被引用
不同点
- init函数可以应用于
任意包
中,且可以重复定义多个
。
补充:- 在同一个package中,可以在多个文件中定义init函数
- 在同一个go文件中,可以重复定义多个init函数
- main函数只能用于
main
包中,且只能定义一个。
下面进入重头戏!
init函数的执行顺序
- 对于同一个package中的不同文件 ,将文件名按照
字符串字典序"从小到大"
进行排序,之后按顺序调用各个文件中的init()
函数。 - 对于同一个文件 的多个
init ()
函数,按照在代码中编写的顺序依次执行不同的init 函数。
官方:同一个包中多个init函数的执行顺序go语言
没有明确的定义(说明)
面试时可以说虽然官方的说法是这样,但是实际上运行时执行的顺序如上描述
-
对于不同的package ,如果不相互依赖 的话,按照
main
包中的import
的顺序调用其包中的init()
函数。 -
如果
package
存在依赖 ,调用顺序为最后被依赖的最先被初始化 ,例如:导入顺序:main->A->B->C
,则初始化顺序为C->B->A->main
,依次执行对应的init ()
函数。
注意:
所有init函数都在同一个goroutine内执行。
所有init函数结束后才会执行main.main函数。
面试官:多个包 init 的执行顺序?单个包多个 init 函数的执行顺序, init 函数的用途?
多个包init的执行顺序
-
对于不同的package ,如果不相互依赖 的话,按照
main
包中的import
的顺序调用其包中的init()
函数。 -
如果
package
存在依赖 ,调用顺序为最后被依赖的最先被初始化 ,例如:导入顺序:main->A->B->C
,则初始化顺序为C->B->A->main
,依次执行对应的init ()
函数。
单个包多个init函数的执行顺序
- 对于同一个package中的不同文件 ,将文件名按照
字符串字典序"从小到大"
进行排序,之后按顺序调用各个文件中的init()
函数。 - 而对于同一个文件 的多个
init ()
函数,按照在代码中编写的顺序
依次执行不同的init
函数。
官方:同一个包中多个init函数的执行顺序go语言
没有明确的定义(说明)
面试时可以说虽然官方的说法是这样,但是实际上运行时执行的顺序如上描述
init函数的用途
init函数是用于程序执行前初始化包的函数 ,比如初始化包里的全局变量
等
- 初始化
不能采用初始化表达式初始化
的变量。 - 程序
运行前的注册
。 - 实现
sync.Once
功能。 - 其他
看到这里的小伙伴,恭喜你又掌握了一个知识点👊
希望大家能取得胜利,坚持就是胜利💪
我是寸铁!我们下期再见💕