# 4.3 符号解析

类型检查最重要的一件事情就是做符号解析，所谓符号解析，就是将程序中通过“名字”所引用的真实对象找出来。这里所说的“名字”，在词法分析阶段对应的 Token 类型是`_Name`, 而在语法阶段对应的表达式是`Name`，其定义如下：

```go
// file: $GCROOT/compile/internal/syntax/nodes.go
type Name struct {
	Value string
	expr
}

```

名字所引用的对象就是语言中某个类型的具体实例，例如函数、变量等。例如下列代码涉及到的名字包括：A, main, a, name, fmt, Printf.

```go
import "fmt"

type A struct{}

func main() {
	var a A
	name := "Golang"

	fmt.Printf("%v-%s\n", a, name)
}

```

go 的编译单位是 package, 即每次编译的源文件必须属于同一个包，所以涉及到的符号来源可以简单归为如下几类：&#x20;

1. 预定义符号，即内置符号，包括语言的内置类型、内置函数、泛型的内置 constraints 等
2. 当前源文件所依赖的包，即通过 \~import\~ 语句引用的各个 package
3. 当前源文件自定义的符号，即定义的类型、变量等

为了完成符号解析，编译器需要构建一个符号表，其在编译的初始化阶段会注册第一部分的符号，在类型检查时导入第二部分的符号，并在实际类型检查过程中对第三部分的符号进行处理。除了符号注册，编译器还需要对符号的作用域进行管理，即处理好哪些符号是 public 的，哪些是 package local 的，哪些是 function local 的。为了管理好这些逻辑，编译器需要定义各种数据结构来抽象对应的概念，我们将在下一节详细分析类型检查时所涉及到的重要数据结构。
