# 4.5.2-1 全局作用域

简单地说，该部分的任务就是将语言的[内置符号](https://gocompiler.shizhz.me/golang-bian-yi-qi-lei-xing-jian-cha/4.3-fu-hao-jie-xi)初始化，并注册到[全局作用域](https://gocompiler.shizhz.me/golang-bian-yi-qi-lei-xing-jian-cha/4.4.1-shu-ju-jie-gou-zuo-yong-yu)中。初始化逻辑在`$GCROOT/compile/internal/types2/universe.go`中，通过`init`函数在编译器启动时自动初始化：

```go
func init() {
	Universe = NewScope(nil, nopos, nopos, "universe") // 实例化全局作用域
	Unsafe = NewPackage("unsafe", "unsafe")
	Unsafe.complete = true

	defPredeclaredTypes()
	defPredeclaredConsts()
	defPredeclaredNil()
	defPredeclaredFuncs()
	defPredeclaredComparable()

	universeIota = Universe.Lookup("iota").(*Const)
	universeByte = Universe.Lookup("byte").(*TypeName).typ.(*Basic)
	universeRune = Universe.Lookup("rune").(*TypeName).typ.(*Basic)
	universeAny = Universe.Lookup("any").(*TypeName).typ.(*Interface)
	universeError = Universe.Lookup("error").(*TypeName).typ.(*Named)

	// "any" is only visible as constraint in a type parameter list
	delete(Universe.elems, "any")
}
```

该函数很清晰地表达了整个初始化过程，我们知道`Scope`中存放的是`Object`对象，所以各初始化函数的任务就是创建不同类型的`Object`对象并注册到全局变量`Universe`中。我们简单描述一下各个函数的任务：

* defPredeclaredTypes\
  &#x20;注册基本类型，例如 int8, float32, bool 等，包括前文提到的 Untyped 类型，该函数会为每种类型创建一个`TypeName`类型的 Object 对象。\
  \
  值得注意的是该方法还初始化了 error 类型，初始化代码如下：

```go
{
    res := NewVar(nopos, nil, "", Typ[String])                                // 方法返回类型为 string
    sig := &Signature{results: NewTuple(res)}                                 // 函数类型，只有返回 Tuple, 没有参数 Tuple
    err := NewFunc(nopos, nil, "Error", sig)                                  // 函数对象，函数名为 Error
    typ := &Named{underlying: NewInterfaceType([]*Func{err}, nil).Complete()} // 创建一个 defined type, 其 underlying type 是接口类型
    sig.recv = NewVar(nopos, nil, "", typ)                                    // 设置函数的 receiver, 使其成为上面接口的方法
    def(NewTypeName(nopos, nil, "error", typ))                                // 注册函数类型
}
```

&#x20;       上述代码相当于往 Universe 中注册了如下的接口类型：

```go
type error interface {
    Error() string
}
```

&#x20;       而这正是 go 中对 error 类型的要求：实现`Error() string`方法，所以 error 类型的接口并没有在任何地方进行显示地申明，而是在此处通过代码创建的。

* defPredeclaredConsts\
  &#x20;注册语言内置的常量，一共有三个：true, false, iota. 为每个常量创建一个`Const`类型的 Object 对象。
* defPredeclaredNil\
  注册`nil`, 其对应的是`Nil`类型的 Object 对象。
* defPredeclaredFuncs \
  注册内置函数，例如 append, new, panic 等，每个内置函数对应一个`Builtin`类型的 Object 对象。
* defPredeclaredComparable\
  与注册 error 类型相似，该方法注册了另一个隐式接口 comprable, 该接口是[泛型的预定义 constraint](https://go.googlesource.com/proposal/+/refs/heads/master/design/go2draft-type-parameters.md#comparable-types-in-constraints). 例如可以如下方式使用该接口：

```go
// 使用 comparable 来限定 T 的类型
func compare[T comparable](i, j T) bool {} 
```
