【问题标题】:How are Go closures layed out in memory?Go 闭包在内存中是如何布局的?
【发布时间】:2019-10-10 19:42:41
【问题描述】:

有关闭包的一般解释,请参阅How do JavaScript closures work?

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

以如下函数为例:

type M int

func (m *M) Adder(amount int) func() {
    return func() {
        *m = *m + amount
    }
}

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

【问题讨论】:

  • 看起来runtime/runtime2.go 中的funcval 结构体很有用。
  • 另一个问题是关于 闭包在实践中是如何工作的,但您要问的是来自特定 Go 编译器的未定义版本的实现细节。虽然这可能很有趣,但我不知道 SO 是否适合问。
  • golang 常见问题解答可能会有所帮助:golang.org/doc/faq#stack_or_heap 如果它是函数/闭包等,这对所有人来说都是相似的

标签: go closures


【解决方案1】:

The Go Programming Language Specification

Function literals

函数字面量表示匿名函数。

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)

函数字面量是闭包:它们可以引用定义在 一个周边功能。然后这些变量在 周围的函数和函数字面量,它们作为 只要它们可以访问。


闭包可以引用定义在 一个周边功能。然后这些变量在 周围的函数和函数字面量,它们作为 只要它们可以访问。

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


例如,

func closure() func() *byte {
    var b [4 * 1024]byte
    return func() *byte {
        return &b[0]
    }
}

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

struct { F uintptr; b *[4096]byte }

一个用于 4096 字节

[4096]byte

总共 4112 个字节。

【讨论】:

    猜你喜欢
    • 2016-02-13
    • 2013-01-22
    • 2011-08-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多