# 4.4.3 数据结构 - Object 对象

`Object`定义了一个接口，用来表示程序中的各类命名实体，即前文一直提到的符号对象，例如函数、变量、类型等。编译器内部为不同的符号类型定义了不同的数据结构，所有定义都在文件 `$GCROOT/compile/internal/types2/object.go` 中。

## 4.4.3.1. 接口及公用结构

接口 `type Object interface{...}` 的声明如下：

```go
// An Object describes a named language entity such as a package,
// constant, type, variable, function (incl. methods), or label.
// All objects implement the Object interface.
// 
type Object interface {
	Parent() *Scope  // scope in which this object is declared; nil for methods and struct fields
	Pos() syntax.Pos // position of object identifier in declaration
	Pkg() *Package   // package to which this object belongs; nil for labels and objects in the Universe scope
	Name() string    // package local object name
	Type() Type      // object type
	Exported() bool  // reports whether the name starts with a capital letter
	Id() string      // object name if exported, qualified name if not exported (see func Id)

	// String returns a human-readable string of the object.
	String() string

	// order reflects a package-level object's source order: if object
	// a is before object b in the source, then a.order() < b.order().
	// order returns a value > 0 for package-level objects; it returns
	// 0 for all other objects (including objects in file scopes).
	order() uint32

	// color returns the object's color.
	color() color

	// setType sets the type of the object.
	setType(Type)

	// setOrder sets the order number of the object. It must be > 0.
	setOrder(uint32)

	// setColor sets the object's color. It must not be white.
	setColor(color color)

	// setParent sets the parent scope of the object.
	setParent(*Scope)

	// sameId reports whether obj.Id() and Id(pkg, name) are the same.
	sameId(pkg *Package, name string) bool

	// scopePos returns the start position of the scope of this Object
	scopePos() syntax.Pos

	// setScopePos sets the start position of the scope for this Object.
	setScopePos(pos syntax.Pos)
}

```

该接口申明的方法比较多，但基本都是属性的 Getter 或者 Setter 方法，公用信息定义在结构`type object struct{...}`中，具体声明如下：

```go
type object struct {
	parent    *Scope
	pos       syntax.Pos
	pkg       *Package
	name      string
	typ       Type
	order_    uint32
	color_    color
	scopePos_ syntax.Pos
}
```

object 完整地实现了`Object`接口。其中`color_`属性用于后期的[对象循环依赖检查](https://gocompiler.shizhz.me/golang-bian-yi-qi-lei-xing-jian-cha/4.5.32a-dui-xiang-xun-huan-yi-lai-jian-cha)，而`typ`属性用来保存该对象的实际类型，类型推导目的就是要为每个对象推导出该属性，[类型数据结构](https://gocompiler.shizhz.me/4.4.1-shu-ju-jie-gou-zuo-yong-yu#32-lei-xing-shu-ju-jie-gou)一节将会详细介绍各种类型的数据结构。

## 4.4.3.2. 具体Object类型

编译器一共定义了 8 类 Object, 包括：

* PagName: 包对象
* Const: 常量对象
* TypeName: 代表通过`type`关键字定义的类型，或者类型别名
* Var: 代表一个变量声明，通过用来表示函数的参数、返回值，以及结构体的 Field
* Func: 代表一个方法、函数声明，或者接口内的方法声明
* Label: 代表程序内的一个 label, 用于 break, goto 等关键字；其没有 type 属性
* Builtin: 代表一个内置函数
* Nil: 代表 nil 值
* dependency: 用来标识初始化表达式可能依赖的对象，只有`Const`, `Var`, 以及`Func`是合法的该类对象。该类对象用于构建全局变量的初始化顺序，这在后面会有详细介绍。

每种类型的自定义属性并不多，基本都只是复用了 object, 所以在这里就不一一列举代码了，详情请读者自行查阅`$GCROOT/compile/internal/types2/object.go`。

## 4.4.3.3. Object对象的等价性

每个 Object 对象都代表着程序的一个符号，所以只有指向同一个符号的两个 Object 对象才是等价的，而在不同作用域的两个符号即使在结构上完全一样，也是不同的对象，这一点与类型的等价规则不同。[类型的等价规则](https://gocompiler.shizhz.me/golang-bian-yi-qi-lei-xing-jian-cha/4.4.412-lei-xing-de-deng-jia-gui-ze-fl)会在后面详细介绍。

## 4.4.3.4. Object的作用

Object 对象是类型检查的重要数据结构，准确地说，该对象的内部封装了符号对象的各方面信息：包、作用域、类型、位置信息等；每一个 Object 都与 AST 中的一个节点（Node）对应，类型检查器保存了这两类信息的映射关系（[Checker](https://gocompiler.shizhz.me/4.4.5-lei-xing-jian-cha-qi#3-checker) 的 objMap 属性）。

类型检查的目的，就是将所有 Object 对象的类型属性，即 object 中的 typ 属性推导出来，并检查整个类型系统的兼容性。事实上，类型检查的整个逻辑都是围绕着 Object 对象展开的，我们会在[类型检查逻辑](https://gocompiler.shizhz.me/golang-bian-yi-qi-lei-xing-jian-cha/lei-xing-jian-cha-luo-ji)一节对其进行详细分析。在此之前，我们先来熟悉一下编译器内部的类型数据结构。
