08|入口函数与包初始化:搞清Go程序的执行次序
该思维导图由 AI 生成,仅供参考
main.main 函数:Go 应用的入口函数
- 深入了解
- 翻译
- 解释
- 总结
本文深入介绍了Go程序的执行次序和包的初始化次序,通过对入口函数main.main和包初始化函数init的详细讲解,帮助读者快速了解了Go程序的执行逻辑。文章从init函数的用途出发,阐述了init函数在包初始化过程中的重要性,包括重置包级变量值、实现对包级变量的复杂初始化以及在init函数中实现“注册模式”。通过实例代码和流程图,读者可以清晰地了解Go程序启动后,包的初始化次序是否正确。此外,文章还强调了init函数的特殊行为特征,如执行顺位、仅执行一次以及顺序执行等。总之,本文通过深入浅出的方式,全面介绍了Go程序的执行次序和包的初始化次序,为读者提供了清晰的指导和实用的技术知识。读者可以通过本文快速了解Go程序的执行逻辑,为自己的程序编写提供指导和帮助。
《Tony Bai · Go 语言第一课》,新⼈⾸单¥59
全部留言(57)
- 最新
- 精选
- andox分情况而定 1. 初始化失败的是必要的数据 panic处理 结束进程 1. 初始化失败的是对业务没影响,可成功可失败的 输出warn或error日志 方便定位
作者回复: 手动点赞!
2021-10-29298 - 多选参数同一个包内有多个源文件的话,这个包是将所有源文件的常量、变量、init() 函数汇集到一起,然后常量-变量-init() 这样的顺序进行初始化,而不是每个源文件走一遍常量-变量-init() 这样的顺序,是嘛?老师
作者回复: 问题很好。实测情况是go会先按文件传入顺序,分别初始化常量与变量,然后在分别调用各个文件中的init函数。比如说如果一个pkg1有两个文件file1.go和file2.go,那么初始化顺序是:file1中的常量 -> file1中的变量 -> file2中常量 -> file2中变量 -> file1中init函数 -> file2中init函数。
2021-11-161351 - 奕go 循环依赖是怎么处理的?
作者回复: go不允许循环依赖。编译器会检测并报错。
2021-10-29225 - Calvin简单做个笔记: - Go 包的初始化次序: 1)依赖包按“深度优先”的次序进行初始化; 2)每个包内按以“常量 -> 变量 -> init 函数”(main.main 函数前)的顺序进行初始化; 3)包内的多个 init 函数按出现次序进行自动调用。 - init 函数常见用途: 1)重置包级变量值; 2)实现对包级变量的复杂初始化; 3)在 init 函数中实现“注册模式”(工厂设计模式)- 空导入。 - init 函数具备的几种行为特征(init 函数十分适合做一些包级数据初始化工作以及包级数据初始状态的检查工作): 1)执行顺位排在包内其他语法元素的后面; 2)每个 init 函数在整个 Go 程序生命周期内仅会被执行一次; 3)init 函数是顺序执行的,只有当一个 init 函数执行完毕后,才会去执行下一个 init 函数。
作者回复: 手动点赞!
2021-10-29224 - 谢小路初始化 init 函数先于 main 函数执行,项目中如非必要,禁止隐式的 init 初始化,协作人员多了,各种千奇百怪的问题都可能导致程序执行失败。转而使用显式的初始化,直接在 main 函数中调用对应的初始化方法。
作者回复: 👍
2022-04-24210 - python玩家一枚init失败的话,我感觉一般init中要完成的内容好像都偏向资源属性,如果有必然能成功的默认属性则走默认值并警告,如果是必要资源则不成功会影响后续的运行,这时候应该要直接严重错误告警并终止程序吧
作者回复: 正确✅
2021-10-3027 - 布凡prog-init-order ├── go.mod ├── main.go ├── pkg1 │ └── pkg1.go ├── pkg2 │ └── pkg2.go └── pkg3 └── pkg3.go 怎样在main.go中引用包 _ "github.com/bigwhite/prog-init-order/pkg1" _ "github.com/bigwhite/prog-init-order/pkg2" 有什么特殊的操作吗?因为我在vscode上事件的时候会提示 “could not import xxx(cannot find package "xxx" in any of C:/Program File\Go(from $GOROOT) ……(from $GOPATH))” 意思是GOPATH中找不这个包,就算我将项目变成了一个Go Module 也依然找不到,是我那里理解的有问题吗?还请老师解惑,main中 import是怎样引用到自己的pkg包中的方法呢?
作者回复: gopath模式下肯定不行。go module模式下,检查一下go.mod中module path是否是github.com/bigwhite/prog-init-order?
2021-11-0385 - 进化菌真棒,相当于了解go代码的执行生命周期。 当 init 函数在检查包数据初始状态时遇到失败或错误的情况,我们该如何处理呢?直接返回异常吗?在go里面,异常一般会当成第二个返回值吧。
作者回复: init函数没有返回值,异常是通过panic机制传导的,通常导致程序退出。当 init 函数在检查包数据初始状态时遇到失败或错误的情况,通过panic退出是一个多数的选择。
2021-10-305 - CLMOOK🐾老师好,有个小疑问,为啥init()允许在一个源文件中有多个,与其他func一样不允许同名不是简单点?go这么设计的出发点是什么? 谢谢
作者回复: 1. init函数不是普通函数,就和main函数一样,编译器会有特殊关照,一个包里有多个init不会出现“init已定义”的编译错误。 2. 至于允许存在多个init,这个没有标准答案。日常实践中,我会将不同类型的初始化操作放在不同init(初始化的“内聚”),同一包内的不同文件的内的初始化,都放在各自文件中,这样代码可读性好一些。
2022-09-18归属地:北京4 - lesserrorTony Bai 老师中这一讲很精彩,受益良多。 另外有几个问题,麻烦抽空解答一下: 1. 文中说:“非 main 包中自定义的 main 函数仅限于包内使用?” 那我是否可以理解为:main包中定义的 main函数,包外可以使用? 2. 感觉这个课程应该弄个 GitHub 仓库,提交一些本课程中的代码 ? 便于以后进行代码的学习和复习使用? ps: 老师结合标准库源码来讲代码的使用方法非常棒,个人感觉比举例 用类似阿猫、 阿狗之类的代码更利于上手学习。
作者回复: 1. 不可以。main包中定义的main函数也仅能在main包内使用 2. 好建议。 3. 如果标准库中有合适的例子,我会尽量用标准库的。
2021-10-3024