# 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 内只包含全局变量的初始化逻辑，常量的初始化在类型检查时已经完成，这里处理常量的依赖图只是为了检测循环依赖。


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://gocompiler.shizhz.me/golang-bian-yi-qi-lei-xing-jian-cha/4.5.31.4-gou-jian-chu-shi-hua-shun-xu.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
