问题
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