设为首页收藏本站
网站公告 | 这是第一条公告
     

 找回密码
 立即注册
缓存时间17 现在时间17 缓存数据 这个世界上很多东西会变,很多人会走。 但你在我心里,从开始的那一天,到现在从来没有变过。 我一直在等,等你的消息。

这个世界上很多东西会变,很多人会走。 但你在我心里,从开始的那一天,到现在从来没有变过。 我一直在等,等你的消息。 -- 盛夏的果实

查看: 1685|回复: 2

go语言的初始化顺序,包,变量,init详解

[复制链接]

  离线 

TA的专栏

等级头衔

等級:晓枫资讯-列兵

在线时间
0 小时

积分成就
威望
0
贡献
21
主题
19
精华
0
金钱
69
积分
40
注册时间
2023-9-29
最后登录
2025-5-31

发表于 2024-4-1 20:48:03 | 显示全部楼层 |阅读模式
依次见例子代码:
p1.go
  1. package p1
  2. import "fmt" //1.1
  3. var x float32 = 1.2 //1.2
  4. func init() { //1.3
  5.   fmt.Printf("p1 package, x:%f\n", x) //1.4
  6. }
  7. func Donothing() {
  8.   fmt.Println("do nothing.\n")
  9. }
复制代码
a.go:
  1. package main
  2. import "fmt"
  3. var WhatIsThe1 = AnswerToLife(2.1) //2.1
  4. var WhatIsThe2 = AnswerToLife(2.2) //2.2
  5. var WhatIsThe3 = AnswerToLife(2.3) //2.3
  6. func init() { //3.1
  7.   fmt.Printf("init WhatIsThe in a.go `s init 3.1: %d\n", 2)
  8. }
  9. func init() { //3.2
  10.   fmt.Printf("init WhatIsThe in a.go`s init 3.2: %d\n", 3)
  11. }
复制代码
testinit.go
  1. package main
  2. import "p1" //1
  3. import "fmt"
  4. var WhatIsThe4 = AnswerToLife(2.4) //2.4
  5. var WhatIsThe5 = AnswerToLife(2.5) //2.5
  6. var WhatIsThe6 = AnswerToLife(2.6) //2.6
  7. func AnswerToLife(index float32) float32 {
  8.   fmt.Printf("init package level variable, WhatIsThe: %f\n", index)
  9.   return index
  10. }
  11. func init() { //3.3
  12.   fmt.Printf("init WhatIsThe in testinit.go`s init3.3: %d\n", 0)
  13. }
  14. func init() { //3.4
  15.   fmt.Printf("init WhatIsThe in testinit.go`s init3.4: %d\n", 1)
  16. }
  17. func main() { //4
  18.   p1.Donothing() //5
  19. }
复制代码
z.go
  1. package main
  2. import "fmt"
  3. var WhatIsThe7 = AnswerToLife(2.7) //2.7
  4. var WhatIsThe8 = AnswerToLife(2.8) //2.8
  5. var WhatIsThe9 = AnswerToLife(2.9) //2.9
  6. func init() { //3.5
  7.   fmt.Printf("init WhatIsThe in z.go`s init 3.5: %d\n", 4)
  8. }
  9. func init() { //3.6
  10.   fmt.Printf("init WhatIsThe in z.go`s init 3.6: %d\n", 5)
  11. }
复制代码
代码文件贴出的顺序就是各大块之间的初始化顺序, 具体准确顺序请看,形如//1 , //2.1 这样的注释, 数值从小到大,小的先初始化,依次进行.
总结:

在一个go文件中, 初始化顺序规则: (1)引入的包 (2) 当前包中的变量常量 (3) 当前包的init (4)main函数
注意:
0. 当前go源文件中, 每一个被Import的包, 按其在源文件中出现顺序初始化。
1. 如果当前包有多个init在不同的源文件中, 则按源文件名以字典序从小到大排序,小的先被执行到, 同一包且同一源文件中的init,则按其出现在文件中的先后顺序依次初始化; 当前包的package level变量常量也遵循这个规则; 其实准确来说,应是按提交给编译器的源文件名顺序为准,只是在提交编译器之前, go命令行工具对源文件名按字典序排序了。
2. init只可以由go runtine自已调用, 我们在代码中不可以显示调用,也不可以被引用,如赋给a function variable。
3. 包A 引入包B , 包B又引入包C, 则包的初始化顺序为: C -> B -> A
4. 引入包,必须避免死循环,如 A 引 B , B引C, C引A.
5. 一个包被其它多个包引入,如A -> B ->C 和 H -> I -> C , C被其它包引了2次, 但是注意包C只被初始化一次。
6. 另一个大原则, 被依赖的总是先被初始化,当然呀。
7. main包总是被最后一个初始化,这很好理解,因为它总是依赖别的包。
1.jpeg

补充:golang入门-- import包与包内init方法的执行时机
最近在学习revel(golang web开发框架) ,了解到revel管理和加载所有controller的方式。其中涉及的golang基础知识是import包。下面我们先来看看golang imort包的几种方法和特征:
第一种方式相对路径
  1. import "./module" //当前文件同一目录的module目录, 此方式没什么用容易出错</span>
复制代码
第二种方式绝对路径
  1. import “LearnGo/init” //加载gopath/src/LearnGo/init模块
复制代码
下面展示一些特殊的import方式

1.点操作
我们有时候会看到如下的方式导入包
  1. import( . “fmt” )
复制代码
这个点操作的含义就是这个包导入之后在你调用这个包的函数时,你可以省略前缀的包名,也就是前面你调用的fmt.Println("hello world")可以省略的写成Println("hello world")
2.别名操作
别名操作顾名思义我们可以把包命名成另一个我们用起来容易记忆的名字,revel框架的app/controllers/tmp/main.go(框架的启动入口)里可以看到此方式的应用。
  1. import(
  2. f "fmt"
  3. )
复制代码
别名操作的话调用包函数时前缀变成了我们的前缀,即f.Println("hello world")。
  1. import (//revel框架的代码片段
  2. "flag"
  3. "reflect"
  4. "github.com/revel/revel"
  5. controllers0 "github.com/revel/modules/static/app/controllers"
  6. _ "github.com/revel/modules/testrunner/app"
  7. controllers1 "github.com/revel/modules/testrunner/app/controllers"
  8. _ "guild_website/app"
  9. controllers "guild_website/app/controllers"
  10. tests "guild_website/tests"
  11. "github.com/revel/revel/testing"
  12. )
复制代码
3._操作
这个操作经常是让很多人费解的一个操作符,请看下面这个import
  1. import (//revel框架的代码片段
  2. _ "github.com/revel/modules/testrunner/app"
  3. _ "guild_website/app"
  4. )
复制代码
_操作其实是引入该包,而不直接使用包里面的函数,而是调用了该包里面的init函数,要理解这个问题,需要看下面这个图,理解包是怎么按照顺序加载的:
程序的初始化和执行都起始于main包。如果main包还导入了其它的包,那么就会在编译时将它们依次导入。
有时一个包会被多个包同时导入,那么它 只会被导入一次(例如很多包可能都会用到fmt包,但它只会被导入一次,因为没有必要导入多次)。当一个包被导入时,如果该包还导入了其它的包,那么会先 将其它包导入进来,然后再对这些包中的包级常量和变量进行初始
化,接着执行init函数(如果有的话),依次类推。等所有被导入的包都加载完毕了,就会开 始对main包中的包级常量和变量进行初始化,然后执行main包中的init函数(如果存在的话),最后执行main函数。
此外需了解别名操作方式导入包也会执行init函数。
2.jpeg

以上为个人经验,希望能给大家一个参考,也希望大家多多支持晓枫资讯。如有错误或未考虑完全的地方,望不吝赐教。

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!
晓枫资讯-科技资讯社区-免责声明
免责声明:以上内容为本网站转自其它媒体,相关信息仅为传递更多信息之目的,不代表本网观点,亦不代表本网站赞同其观点或证实其内容的真实性。
      1、注册用户在本社区发表、转载的任何作品仅代表其个人观点,不代表本社区认同其观点。
      2、管理员及版主有权在不事先通知或不经作者准许的情况下删除其在本社区所发表的文章。
      3、本社区的文章部分内容可能来源于网络,仅供大家学习与参考,如有侵权,举报反馈:点击这里给我发消息进行删除处理。
      4、本社区一切资源不代表本站立场,并不代表本站赞同其观点和对其真实性负责。
      5、以上声明内容的最终解释权归《晓枫资讯-科技资讯社区》所有。
http://bbs.yzwlo.com 晓枫资讯--游戏IT新闻资讯~~~

  离线 

TA的专栏

等级头衔

等級:晓枫资讯-列兵

在线时间
0 小时

积分成就
威望
0
贡献
0
主题
0
精华
0
金钱
20
积分
20
注册时间
2022-12-27
最后登录
2022-12-27

发表于 2025-2-18 01:00:56 | 显示全部楼层
路过,支持一下
http://bbs.yzwlo.com 晓枫资讯--游戏IT新闻资讯~~~

  离线 

TA的专栏

等级头衔

等級:晓枫资讯-列兵

在线时间
0 小时

积分成就
威望
0
贡献
0
主题
0
精华
0
金钱
16
积分
12
注册时间
2022-12-27
最后登录
2022-12-27

发表于 2025-3-21 18:48:57 | 显示全部楼层
顶顶更健康!!!
http://bbs.yzwlo.com 晓枫资讯--游戏IT新闻资讯~~~
严禁发布广告,淫秽、色情、赌博、暴力、凶杀、恐怖、间谍及其他违反国家法律法规的内容。!晓枫资讯-社区
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

1楼
2楼
3楼

手机版|晓枫资讯--科技资讯社区 本站已运行

CopyRight © 2022-2025 晓枫资讯--科技资讯社区 ( BBS.yzwlo.com ) . All Rights Reserved .

晓枫资讯--科技资讯社区

本站内容由用户自主分享和转载自互联网,转载目的在于传递更多信息,并不代表本网赞同其观点和对其真实性负责。

如有侵权、违反国家法律政策行为,请联系我们,我们会第一时间及时清除和处理! 举报反馈邮箱:点击这里给我发消息

Powered by Discuz! X3.5

快速回复 返回顶部 返回列表