有关闭包的一般说明,请参见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()
值占用多少内存(无论它在内存中的什么位置)?
答案 0 :(得分:0)
golang常见问题解答可能会有所帮助:https://golang.org/doc/faq#stack_or_heap
我怎么知道是在堆上还是在栈上分配了变量?
从正确性的角度来看,您不需要知道。只要有引用,Go中的每个变量都存在。该实现选择的存储位置与该语言的语义无关。
存储位置确实会影响编写高效的程序。如果可能,Go编译器将在该函数的堆栈框架中分配该函数本地的变量。但是,如果编译器无法证明函数返回后未引用该变量,则编译器必须在垃圾回收堆上分配该变量,以避免悬空指针错误。另外,如果局部变量很大,则将其存储在堆中而不是堆栈中可能更有意义。
在当前的编译器中,如果使用了变量的地址,则该变量是在堆上分配的候选对象。但是,基本的转义分析可以识别某些情况,即此类变量不会超出函数的返回范围,而是可以驻留在堆栈中。
答案 1 :(得分:-1)
The Go Programming Language Specification
函数文字代表一个匿名函数。
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字节。