Go 的闭包在内存中是如何布局的?

Rik*_*ing 5 closures go

有关闭包的一般解释,请参阅JavaScript 闭包如何工作?

Go 闭包在内存中究竟是如何布局的?

以下面的函数为例:

type M int

func (m *M) Adder(amount int) func() {
    return func() {
        *m = *m + amount
    }
}
Run Code Online (Sandbox Code Playgroud)

当我们的代码调用 时a := m.Adder(),堆上分配了多少内存,它是什么样子的?返回func()值占用多少内存(无论它最终在内存中的哪个位置)?

pet*_*rSO 5

Go 编程语言规范

函数字面量

函数文字表示匿名函数。

FunctionLit = "func" Signature FunctionBody .

func(a, b int, z float64) bool { return a*b < int(z) }

函数文字可以分配给变量或直接调用。

f := func(x, y int) int { return x + y }
func(ch chan int) { ch <- ACK }(replyChan)
Run Code Online (Sandbox Code Playgroud)

函数字面量是闭包:它们可以引用在周围函数中定义的变量。然后这些变量在周围的函数和函数文字之间共享,只要它们可以访问,它们就会存在。


闭包可以指在周围函数中定义的变量。然后这些变量在周围的函数和函数文字之间共享,只要它们可以访问,它们就会存在。

在函数调用中幸存下来的变量被放在堆上。在 Go 中,闭包就是这么简单。


例如,

func closure() func() *byte {
    var b [4 * 1024]byte
    return func() *byte {
        return &b[0]
    }
}
Run Code Online (Sandbox Code Playgroud)

一个closure()调用是两个堆分配,一个用于 16 (= 8 + 8 on amd64) 字节

struct { F uintptr; b *[4096]byte }
Run Code Online (Sandbox Code Playgroud)

一个为 4096 字节

[4096]byte
Run Code Online (Sandbox Code Playgroud)

总共 4112 个字节。