Links
Comment on page

4.5.2-1 全局作用域

简单地说,该部分的任务就是将语言的内置符号初始化,并注册到全局作用域中。初始化逻辑在$GCROOT/compile/internal/types2/universe.go中,通过init函数在编译器启动时自动初始化:
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 注册基本类型,例如 int8, float32, bool 等,包括前文提到的 Untyped 类型,该函数会为每种类型创建一个TypeName类型的 Object 对象。 值得注意的是该方法还初始化了 error 类型,初始化代码如下:
{
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)) // 注册函数类型
}
上述代码相当于往 Universe 中注册了如下的接口类型:
type error interface {
Error() string
}
而这正是 go 中对 error 类型的要求:实现Error() string方法,所以 error 类型的接口并没有在任何地方进行显示地申明,而是在此处通过代码创建的。
  • defPredeclaredConsts 注册语言内置的常量,一共有三个:true, false, iota. 为每个常量创建一个Const类型的 Object 对象。
  • defPredeclaredNil 注册nil, 其对应的是Nil类型的 Object 对象。
  • defPredeclaredFuncs 注册内置函数,例如 append, new, panic 等,每个内置函数对应一个Builtin类型的 Object 对象。
  • defPredeclaredComparable 与注册 error 类型相似,该方法注册了另一个隐式接口 comprable, 该接口是泛型的预定义 constraint. 例如可以如下方式使用该接口:
// 使用 comparable 来限定 T 的类型
func compare[T comparable](i, j T) bool {}