Go 如何获取对延迟函数的引用?
声明:“一个延迟语句将一个函数调用推送到一个列表上。”我想知道是否可以从程序中的另一个位置访问该列表中的元素,然后调用它们?我可以多次调用它们吗?我假设我有一个对具有延迟行为的函数的引用(如果有帮助的话) 下面是我想做的一个简短示例:Go 如何获取对延迟函数的引用?,go,Go,声明:“一个延迟语句将一个函数调用推送到一个列表上。”我想知道是否可以从程序中的另一个位置访问该列表中的元素,然后调用它们?我可以多次调用它们吗?我假设我有一个对具有延迟行为的函数的引用(如果有帮助的话) 下面是我想做的一个简短示例: func main { doStuff = func() { // open database connections // write temporary files // etc...
func main {
doStuff = func() {
// open database connections
// write temporary files
// etc...
defer func() {
// close database connections
// delete temporary files
// etc...
}()
}
AwesomeApplication(doStuff)
}
func AwesomeApplication(doStuff func()) {
// Now, can I get a reference to the defer function within `doStuff`?
// No, I can't just define the defer function somewhere an pass it
// with `doStuff`. Think of this as a curiosity I want to satisfy,
// not a real use case.
}
存储
延迟
调用的“列表”是完全特定于实现的,因此您没有可靠的方法访问此列表,,可以找到*g编译器系列的实现详细信息(尽管有点旧)
延迟函数与当前goroutine()和
(对于*g系列)由当前堆栈指针标识。如果当前堆栈帧匹配
存储在最顶端的Defer
条目中的堆栈帧,调用此函数
有了这些知识,就可以使用cgo访问延迟函数列表。
你需要知道
- 当前堆栈指针
- 函数的地址
- 当前的goroutine
func setupRoutines() (setUp, tearDown func()) {
// store db connection object and such
return func() { /* connect db and such */ }, func() { /* close db and such */ }
}
然后,您可以在代码中共享tearDown
函数,该函数将使用defer
调用。
通过这种方式,您仍然可以获得所有数据库连接和本地连接的好处,但是
能够共享初始化/断开连接功能
摆弄
如果您真的对使用unsafe
和C感兴趣,可以使用以下代码作为模板
inspect/runtime.c:
// +build gc
#include <runtime.h>
void ·FirstDeferred(void* foo) {
foo = g->defer->fn;
FLUSH(&foo);
}
推迟
package main
import "defer/inspect"
func f(a, b int) {
println("deferred f(", a, b, ")")
}
func main() {
defer f(1, 2)
println( inspect.FirstDeferred() )
}
此代码(基于)允许您访问当前的go例程(g
),因此
它的defer
属性。因此,您应该能够访问该函数的指针
然后用go
FuncVal
将其包装并返回。感谢您的深入解释。我希望它会更简单,可能是一个标准的库函数。我想我知道这不会很好。可悲的是,标准库中没有这方面的内容。然而,我不认为这有什么好处,因为它可以很容易地使用闭包进行建模。如果你认为这对标准图书馆有好处,你可以开一张票。:)我认为我的用例不适合标准库。我同意关闭是一条路要走。谢谢你提供的信息。非常好的回答+1.
package main
import "defer/inspect"
func f(a, b int) {
println("deferred f(", a, b, ")")
}
func main() {
defer f(1, 2)
println( inspect.FirstDeferred() )
}