> 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.4.1-shu-ju-jie-gou-zuo-yong-yu.md).

# 4.4.1 数据结构 - 作用域

作用域是编程语言的一个重要课题，go 语言采用的是静态作用域，即词法作用域。在编译器内部，根据作用域范围从大到小将其划分为：

1. 全局作用域，该作用域内的对象在任何地方都可以访问，编译器中叫 `Universe`
2. 包作用域
3. 文件作用域，该作用域只在编译器内部使用，语言层面没有体现
4. 块作用域，简单说即 `{}` 包围起来的代码片段，例如函数体、控制语句块（例如 if, for 等内部）

编译器采用树形结构来管理作用域，对应的数据结构定义在文件 $GCROOT/compile/internal/types2/scope.go 中：

```go
type Scope struct {
    parent   *Scope            // 当前作用域的父作用域
    children []*Scope          // 当前作用域的子作用域
    elems    map[string]Object // 当前作用域所包含的符号对象，key 是符号名称
    pos, end syntax.Pos        // 作用域位置信息
    comment  string            // for debugging only
    isFunc   bool              // set if this is a function scope (internal use only)
}
```

`Scope` 定义了插入与查找符号的方法：

```go
func (s *Scope) Lookup(name string) Object                                 { /* 忽略函数体 */ }
func (s *Scope) LookupParent(name string, pos syntax.Pos) (*Scope, Object) { /* 忽略函数体 */ }
func (s *Scope) Insert(obj Object) Object                                  { /* 忽略函数体 */ }
```

`Lookup` 仅在本作用域内查找符号， `LookupParent` 则从当前作用域开始，顺着父作用域一直查找，这两个方法是进行符号解析的 API。 `elems` 用来存放当前作用域内名字到符号对象的映射，符号对象是实现了 `Object` 接口的结构，在后续会专门介绍。
