什么是内存分配,当你在Golang返回一个函数?



这里是一个简化的代码

func MyHandler(a int) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.WriteCode(a)
})
}

每当一个http请求来,MyHandler将被调用,它将返回一个函数,将用于处理请求。因此,每当http请求到来时,将创建一个新的函数对象。函数作为Go中的第一类。我试图理解当你从记忆的角度返回一个函数时实际发生了什么。当你返回一个值时,例如一个整数,它将在堆栈中占用4个字节。那么返回一个函数和函数体内的很多东西呢?这是一种有效的方法吗?缺点是什么?

如果您不习惯闭包,它们可能看起来有点神奇。然而,它们很容易在编译器中实现:

  • 编译器查找所有必须为闭包捕获的的变量。它将它们放入一个工作区,只要闭包本身存在,该工作区将被分配并保持分配状态。

  • 编译器然后生成内部函数,带有一个秘密的额外参数,或一些其他运行时技巧,1这样调用函数激活闭包。

因为返回的函数通过编译时的安排访问它的闭包变量,所以没有什么特别需要的。由于Go是一种垃圾收集语言,因此也不需要其他任何东西:指向闭包的指针使闭包数据保持活跃,直到指针消失,因为不能再调用函数,此时闭包数据会蒸发(好吧,在下一次GC时)。


1GCC有时使用trampolines为C完成此操作,其中trampolines是在运行时生成的可执行代码。可执行代码可以设置一个寄存器或传递一个额外的参数等。这可能是昂贵的,因为在运行时被视为数据的东西(生成的代码)必须在运行时转换为可执行代码(可能需要一个系统调用,并可能需要一些监督代码"审查")。生成的运行时代码)。

Go不需要这些,因为语言是用闭包定义的,所以实现者不会,嗯,"关闭"。有什么简单的办法吗。一些运行时abi的定义也考虑了闭包,例如,寄存器r1被保留为所有指针到函数类型的闭包变量指针,或者诸如此类的。

实际函数大小无关。当您返回这样的函数时,将为闭包分配内存,也就是说,为函数使用的作用域中的任何变量分配内存。在这种情况下,将返回一个包含函数地址的指针和一个指向闭包的指针,闭包将包含对变量a的引用。

最新更新