通过接口引用使用变量时,您是否知道Go运行时中到底发生了什么? 这不是一个小问题,因为在Go语言中,实现接口的类型不包含对该接口的任何引用。 尽管如此,我们仍可以尝试使用我们对Go编译器的知识来回答它,这在上一篇博客文章中已经讨论过。

因此,让我们深入研究Go编译器:创建一个基本的Go程序,并查看Go类型转换的内部工作原理。 以它为例,我们将解释如何生成和利用节点树。 因此,您可以进一步将此知识应用于其他Go编译器的功能。

在你开始之前

为了进行实验,我们需要直接使用Go编译器(而不是Go工具)。 您可以使用以下命令访问它。

go tool 6g test.go

它将编译test.go源文件并创建一个目标文件。 在这里,6g是我们计算机上具有AMD64架构的编译器的名称。 请注意,对于不同的体系结构,应使用不同的编译器。

当我们直接使用编译器时,我们可以使用一些方便的命令行参数(更多详细信息在官方文档中)。 为了本实验的目的,我们需要-W标志,该标志将打印节点树的布局。

创建一个简单的Go程序

首先,我们将创建一个示例Go程序。 您将在下面找到我们的版本。

package main
type I interface {
   DoSomeWork()
}
type T struct {
   a int
}
func (t *T) DoSomeWork() {
}
func main() {
   t := &T{}
   i := I(t)
   print(i)
}

真的很简单,不是吗? 唯一似乎不必要的是第17行,我们在其中提供了i变量。 但是,如果没有它,我将保持不使用状态,并且该程序将不会编译。 下一步是使用-W开关编译程序。

go tool 6g -W test.go

完成此操作后,您将看到包含程序中定义的每个方法的节点树的输出。 在我们的情况下,这些是main和init方法。 后者在这里,因为它是为所有程序隐式定义的,但实际上我们现在不在乎。

对于每种方法,编译器都会打印两个版本的节点树。 第一个是我们在解析源文件后获得的原始节点树。 第二个是我们经过类型检查并应用了所有必要修改后得到的版本。


xxx小M
30 声望11 粉丝

暂时放一些读书笔记, 很多内容没有整理好