go 程序初始化

本文代码地址:go 程序初始化

一、package 的作用

1.1 包是什么

包是 golang 的最小组织单元 , 每个.go文件的第一行必须是package 包名(明确回答了我是谁的问题),一个目录下的所有.go文件必须属于同一个包

注意看我这个目录结构:

bash 复制代码
[vect@ubuntu-dev ~/golang/priciple/go_tour]$ tree
.
├── go.mod
├── main.go
├── package1
│   └── package1.go
├── package2
│   └── package2.go
└── utils
    └── utils.go

4 directories, 5 files

go_tour入口包,生成可执行文件

go_tour/package1 是普通库包,被 main 引用

go_tour/package2是普通库包,被 package1 引用

go_tour/utils 是工具包,被多个包引用

1.2 包 = 命名空间 + 访问控制

golang 复制代码
var Val1 = ...  // 大写开头 → 导出,其他包可用:package2.Val1
var val1 = ...  // 小写开头 → 私有,仅本包内可用

golang 所有的设计都是如此,不论是变量、函数、方法等,只要首字母大写,就表明导出,可以被其他包使用

二、init 函数的作用

2.1 init 是什么

init() 是 golang 的自动初始化函数,不需要手动调用,golang 运行时自动执行,有如下特点:

  • 无参无返回值
  • 不能被其它函数调用(main也不行)
  • 一个包内可以有多个init(),按照源文件字母序->同一文件内从上到下一次执行的顺序

例如,我的main.go中有两个init()

golang 复制代码
func init() { fmt.Println("init func1 in main") }  // 先执行
func init() { fmt.Println("init func2 in main") }  // 后执行

2.2 init 的用途

  • 注册驱动
  • 初始化全局配置
  • 校验环境变量

这些动作只需要做一次,所以,不管包被导入多少次,包内的init()只会执行一次

三、golang 程序初始化全流程

初始化遵循依赖图,按照被依赖者优先原则:

从叶子节点(无依赖的utils 和 package2)开始初始化,逐层往上

每个包内又分两步:

  1. 包内变量初始化,按照声明顺序
  2. 执行 init()函数

按照详细的顺序来:

text 复制代码
程序启动
  │
  ├─► 导入 main,发现 import "go_tour/package1"
  │     │
  │     ├─► 导入 package1,发现 import "go_tour/package2" 和 "go_tour/utils"
  │     │     │
  │     │     ├─► 导入 package2,发现 import "go_tour/utils"
  │     │     │     │
  │     │     │     ├─► 导入 utils(无依赖,最底层)
  │     │     │     │     └─► utils 包初始化完毕
  │     │     │     │
  │     │     │     ├─► 初始化 package2 包级变量:Val1, Val2
  │     │     │     └─► 执行 package2 的 init()
  │     │     │
  │     │     ├─► utils 已初始化,复用(不重复执行)
  │     │     ├─► 初始化 package1 包级变量:V1, V2
  │     │     └─► 执行 package1 的 init()
  │     │
  │     ├─► 初始化 main 包级变量:MainVal1, MainVal2
  │     └─► 执行 main 的 init()
  │
  └─► 执行 main()

注意以下关键要点:

规则 说明
每个包只初始化一次 utils 被 package1 和 package2 同时引用,但 TraceLog 输出只出现 6 次(而非更多),因为 utils 的变量和 init 只跑一遍
依赖先行 被 import 的包一定先于 import 它的包初始化
变量先于 init 同一包内,包级变量初始化 → init() → 这才轮到被其他包引用
禁止循环依赖 如果 A import B 且 B import A,编译直接报错
_ 导入也会触发初始化 import _ "pkg" 不引用任何导出符号,但仍会执行该包的变量初始化和 init()

done~

相关推荐
时间的拾荒人1 小时前
C语言字符函数与字符串函数完全指南
c语言·开发语言
2501_948106912 小时前
计算机毕业设计之基于jsp教科研信息共享系统
java·开发语言·信息可视化·spark·课程设计
取经蜗牛2 小时前
Python 第一阶段完全指南:从零到第一个实用工具
开发语言·python
不会c+2 小时前
02-SpringBoot配置文件
java·spring boot·后端
dog2502 小时前
从重尾到截断流量模型的演进
开发语言·php
qq_401700413 小时前
Qt QSS 完全入门写出漂亮界面以及解决样式不生效问题
开发语言·qt
雨辰AI4 小时前
生产级实战:人大金仓 V9 标准化运维手册(日常巡检 + 监控告警 + 应急处置)
java·运维·数据库·后端
我是一颗柠檬4 小时前
【Java项目技术亮点】覆盖索引与索引下推优化
android·java·开发语言
2601_962440844 小时前
计算机毕业设计之健身房管理系统的设计与实现
java·开发语言·课程设计·旅游·宠物
TeamDev4 小时前
JxBrowser 9.3.0 版本发布啦!
java·后端·c#·混合应用·jxbrowser·浏览器控件·异步媒体设备