How are Go closures layed out in memory?

天大地大妈咪最大 提交于 2019-12-21 21:45:34

问题


For an explanation of closures in general, see How do JavaScript closures work?

How exactly are Go closures laid out in memory?

Take, for example, the following function:

type M int

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

When our code calls a := m.Adder(), how much memory is allocated on the heap and what does it look like? How much memory does the returned func() value take up (wherever in memory it ends up being)?


回答1:


The Go Programming Language Specification

Function literals

A function literal represents an anonymous function.

FunctionLit = "func" Signature FunctionBody .

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

A function literal can be assigned to a variable or invoked directly.

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

Function literals are closures: they may refer to variables defined in a surrounding function. Those variables are then shared between the surrounding function and the function literal, and they survive as long as they are accessible.


Closures may refer to variables defined in a surrounding function. Those variables are then shared between the surrounding function and the function literal, and they survive as long as they are accessible.

Variables that survive a function call are put on the heap. In Go, closures are really that simple.


For example,

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

A closure() call is two heap allocations, one for 16 (= 8 + 8 on amd64) bytes

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

and one for 4096 bytes

[4096]byte

for a total of 4112 bytes.




回答2:


The golang FAQ might help: https://golang.org/doc/faq#stack_or_heap

How do I know whether a variable is allocated on the heap or the stack?

From a correctness standpoint, you don't need to know. Each variable in Go exists as long as there are references to it. The storage location chosen by the implementation is irrelevant to the semantics of the language.

The storage location does have an effect on writing efficient programs. When possible, the Go compilers will allocate variables that are local to a function in that function's stack frame. However, if the compiler cannot prove that the variable is not referenced after the function returns, then the compiler must allocate the variable on the garbage-collected heap to avoid dangling pointer errors. Also, if a local variable is very large, it might make more sense to store it on the heap rather than the stack.

In the current compilers, if a variable has its address taken, that variable is a candidate for allocation on the heap. However, a basic escape analysis recognizes some cases when such variables will not live past the return from the function and can reside on the stack.



来源:https://stackoverflow.com/questions/51489323/how-are-go-closures-layed-out-in-memory

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!