# 4.5.3-2a 对象循环依赖检查

在前文中我们分别讨论了[类型循环依赖](https://gocompiler.shizhz.me/4.5.31.3e-chu-li-delayed-dui-lie#xun-huan-yi-lai-jian-cha), 以及[构建初始化顺序](https://gocompiler.shizhz.me/golang-bian-yi-qi-lei-xing-jian-cha/4.5.31.4-gou-jian-chu-shi-hua-shun-xu)时初始化表达式的循环依赖问题，还有一个循环依赖问题需要考虑：Object 对象的循环依赖问题。

给定一个 Object 对象，类型检查的入口是函数`check.objDecl()`, 该函数的主要职责有两个：&#x20;

1. 对 Object 对象进行类型检查&#x20;
2. 检测被检查对象是否有循环依赖

在上文中我们已经详细讨论了第一个方面的内容，这里我们分析一下第二点。

类型检查器通过记录两个信息来做对象的循环依赖检测：&#x20;

1. 给对象标色[Object 接口](https://gocompiler.shizhz.me/4.4.3-shu-ju-jie-gou-object-dui-xiang#1-jie-kou-ji-gong-yong-jie-gou)给对象的颜色定义了 getter 与 setter 方法（color 与 setColor），每个对象可以有三种不同的颜色： \
   a. 白色（white）：该对象还没有进行类型检查，这也是所有对象的初始颜色 \
   b. 灰色（grey）：该对象正在类型检查中 \
   c. 黑色（black）：该对象已经完成类型检查&#x20;
2. 记录对象检查的路径 对象依赖形成的结构是一个有向图（Directed Graph），类型检查会顺着依赖路径遍历所有的节点。[Checker](https://gocompiler.shizhz.me/4.4.5-lei-xing-jian-cha-qi#3-checker)中定义了一个`objPath`属性，该属性用来记录当前类型检查所遍历过的所有对象，也就是当前的对象依赖路径。

结合这两点我们知道，在任意时刻，`checker.objPath`都保存着所有正在进行类型检查的对象，所以当`check.objDecl()`遇到一个灰色对象时，那么可以肯定我们就遇到了一个循环依赖，并且该对象已经在 objPath 上了。但并不是所有循环依赖都是错误的，例如：

```go
type A struct {
	parent *A
}
```

从 Object 层面来说，该结构体循环依赖于自己，但这种通过指针进行依赖是合法的，所以每次 objDecl 方法检测到循环依赖都会对其合法性进行校验，该方法由方法`check.cycle()`完成。我们知道：类型的合法性与变量的初始化顺序有专门的地方进行校验，所以该方法认为这两种情况合法，除此之外都是非法的。
