Go语言底层原理剖析
上QQ阅读APP看本书,新人免费读10天
设备和账号都新为新人

1.10 闭包重写

在前面的阶段,编译器完成了闭包变量的捕获用于决定是通过指针引用还是值引用的方式传递外部变量。在完成逃逸分析后,下一个优化的阶段为闭包重写,其核心逻辑位于gc/closure.go中。闭包重写分为闭包定义后被立即调用和闭包定义后不被立即调用两种情况。在闭包被立即调用的情况下,闭包只能被调用一次,这时可以将闭包转换为普通函数的调用形式。

上面的闭包最终会被转换为类似正常函数调用的形式,如下所示,由于变量a为引用传递,因此构造的新的函数参数应该为int指针类型。如果变量是值引用的,那么构造的新的函数参数应该为int类型。

如果闭包定义后不被立即调用,而是后续调用,那么同一个闭包可能被调用多次,这时需要创建闭包对象。

如果变量是按值引用的,并且该变量占用的存储空间小于2×sizeof(int),那么通过在函数体内创建局部变量的形式来产生该变量。如果变量通过指针或值引用,但是占用存储空间较大,那么捕获的变量(var)转换成指针类型的“&var”。这两种方式都需要在函数序言阶段将变量初始化为捕获变量的值。