> For the complete documentation index, see [llms.txt](https://gocompiler.shizhz.me/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://gocompiler.shizhz.me/golang-bian-yi-qi-lei-xing-jian-cha/4.5.31.4-gou-jian-chu-shi-hua-shun-xu.md).

# 4.5.3-1.4 构建初始化顺序

全局变量与全局常量之间可能存在相互依赖的情况，如下列代码所示：

```go
// 常量依赖其它常量
const a = b + 5
const b = 1

// 变量依赖其它常量、变量以及函数
const golang = "Golang"

var java = "Java"
var greeting = "Hello: " + lang(golang)

func lang(l string) string {
	if len(l) {
		return java
	}
	return l
}

// 循环依赖
const a = b
const b = c
const c = a + 1
```

为了简化初始化时的执行逻辑，我们需要确定变量的初始化顺序，即按照其依赖关系的拓扑顺序进行初始化，同时也需要检测是否有循环依赖。该逻辑定义在文件`$GCROOT/compile/internal/types2/initorder.go`中，入口方法是`check.initOrder()`。该方法的效果就是初始化 info.InitOrder 字段。

在讨论[Object对象](/golang-bian-yi-qi-lei-xing-jian-cha/4.4.3-shu-ju-jie-gou-object-dui-xiang.md)时我们已经提到过，编译器特别定义了一个[dependency](/golang-bian-yi-qi-lei-xing-jian-cha/4.4.3-shu-ju-jie-gou-object-dui-xiang.md#2-ju-ti-object-lei-xing)对象来标识那些可用于初始化表达式的对象，所有的 Const, Var 以及 Func 对象都属于 dependency 对象。

对象的依赖关系保存在[declInfo](/golang-bian-yi-qi-lei-xing-jian-cha/4.4.5-lei-xing-jian-cha-qi.md#3-checker)的`deps`字段中，在对该对象进行类型检查时，检查器通过函数`func (d *declInfo) addDep(obj Object) {}`将当前对象所依赖的对象保存起来。

计算初始化顺序的算法思路如下：先构建对象依赖关系的有向图（Directed Graph），再以每个节点的依赖数目为权重构建最小堆（Min Heap）并以此堆作为最小优先级队列（Priority Queue），因此队列头部的对象总是依赖其它对象最少的，所以该队列的遍历顺序就是初始化的顺序。

info.InitOrder 内只包含全局变量的初始化逻辑，常量的初始化在类型检查时已经完成，这里处理常量的依赖图只是为了检测循环依赖。
