来自 https://go-review.googlesource.com/c/go/+/437216/2..3/test/closure3.dir/main.go#b255 的翻译:
目前,编译器根据外部函数命名闭包:
package main
func main() {
a := 2
if r := func(x int) int {
b := 3
return func(y int) int {
c := 5
return func(z int) int {
return a*x + b*y + c*z
}(10)
}(100)
}(1000); r != 2350 {
panic("r != 2350")
}
}
对于:
return func(z int) int {
return a*x + b*y + c*z
}(10)
统一的IR生成 main.func1.func2
,而旧的前端生成 main.func1.2
。当调用 ir.NameClosure
时发生差异。旧的前端使用即时外部函数( return func(y int) int { ... }
)作为外部函数,而统一的IR使用最外层( func main() { ... }
)。
@mdempsky认为 func
前缀可能不是必要的,我们可以去掉它。
3条答案
按热度按时间c9x0cxw01#
如果我没有理解错的话,那么IR名称生成可能会破坏goroutine泄漏检查器,例如https://github.com/uber-go/goleak和gleak来自https://github.com/onsi/gomega;这些今天使用函数名的过滤列表来过滤已知的“好”goroutine。
68bkxrlz2#
感谢,这是一个值得记住的有趣用例。
of1yzvn43#
请注意,即使在今天,当我们启用内联时,我们对于函数字面量的命名也是不一致的。这里有一个例子,由于内联,相同的函数字面量被赋予了3个不同的名称:$x_{1e0f1}^{x}$