# 4.5.1 类型检查逻辑 - 包加载器

go 编译器一次编译的最大单元是一个包，输出的结果叫着对象文件（Object File），go 定义了自己的对象文件格式，并以`.a`或者`.o`为后缀存在于文件系统中。在`$GOROOT/pkg/$OS_$ARCH/`目录下就包含了所有标准库的对象文件，例如 linux 系统该目录为：`$GOROOT/pkg/linux_amd64`.

加载器在编译阶段解决包依赖问题，其任务就是通过包名找到对应的对象文件，然后将其解析成为上文提到的[Package](/golang-bian-yi-qi-lei-xing-jian-cha/4.4.2-shu-ju-jie-gou-package.md)对象。加载器可以有各种实现，其接口定义在文件`$GCROOT/compile/internal/types2/api.go`中：

```go
type Importer interface {
	Import(path string) (*Package, error)
}

type ImportMode int

type ImporterFrom interface {
	Importer
	ImportFrom(path, dir string, mode ImportMode) (*Package, error)
}
```

两个接口的区别是方法`ImporterFrom`通过指定目标目录的方式来支持[vendor 机制](https://go.googlesource.com/proposal/+/master/design/25719-go15vendor.md), 而`Importer`无法支持，保留`Importer`接口是为了兼容性考虑，ImportMode 当前没有用途。加载器的实现在`$GCROOT/compile/internal/noder/import.go`中，抛开具体细节，其代码框架为：

```go
type gcimports struct {
	packages map[string]*types2.Package
}

func (m *gcimports) Import(path string) (*types2.Package, error) {
	return m.ImportFrom(path, "" /* no vendoring */, 0)
}

func (m *gcimports) ImportFrom(path, srcDir string, mode types2.ImportMode) (*types2.Package, error) { /* 忽略方法体 */
}
```

可见`Import`只是简单地调用`ImportFrom`方法，而后者负责整个加载解析逻辑。加载器配置在[Config](/golang-bian-yi-qi-lei-xing-jian-cha/4.4.5-lei-xing-jian-cha-qi.md#1-config)中，并在类型检查的入口函数`check2()`中进行初始化，该函数在文件`$GCROOT/compile/internal/noder/irgen.go`中。

{% hint style="info" %}
go 编译过程的最后一件事情就是将编译结果导出成对象文件，所以包加载器只是该过程的一个逆操作，当前加载器的实现也是 Go 编译器团队在重写类型检查器的过程中临时的一个实现，后续可能会修改。

对于对象文件的详细格式、导出逻辑与加载逻辑我们没有必要深挖细刨，只需要掌握如下要点即可：&#x20;

1. 对象文件是二进制格式文件，是编译器的输出，链接器的输入&#x20;
2. 对象文件分为不同的块（Section）来组织数据，例如数据块，代码块，调试信息块等&#x20;
3. 对象文件内包含重定位（Relocation）信息，链接器在将多个对象链接在一起时，主要工作就是为需要重定位的数据或者指令规划内存地址&#x20;
4. go 是静态链接语言，在生成可执行文件时，链接器会将所有依赖的包链接在一起，形成一个独立的可执行文件&#x20;
5. 可以通过工具`go tool objdump`来查看对象文件或者可执行文件的内容
   {% endhint %}


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://gocompiler.shizhz.me/golang-bian-yi-qi-lei-xing-jian-cha/lei-xing-jian-cha-luo-ji.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
