本文指出:“ defer语句将函数调用推送到列表上。” 我想知道是否可以从程序的另一个位置访问该列表中的元素,然后调用它们?我可以多次调用它们吗?我假设我对具有延迟行为(如果有帮助)的函数进行了引用。
因此,这是我想做的简短示例:
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. }
defer调用存储的“列表” 完全是特定于实现的,因此您 没有可靠的方式访问此列表 。1,2个为* G编译器家族中的实现细节(虽然有点老),可以发现在拉斯考克斯的研究博客。
defer
延迟函数与当前goroutine(g->Defer)和当前堆栈指针标识的(对于* g系列)相关联。如果当前堆栈帧与存储在最顶部Defer条目中的堆栈帧匹配,则调用此函数。
g->Defer
Defer
了解了这一点它 是 可以访问的使用CGO延迟功能列表。你得知道
但是,我不建议使用此功能。您描述的用例的一般解决方案是具有以下功能:
func setupRoutines() (setUp, tearDown func()) { // store db connection object and such return func() { /* connect db and such */ }, func() { /* close db and such */ } }
然后tearDown,您可以在代码中共享该函数,该函数将使用调用defer。这样,您仍然可以拥有所有数据库连接以及此类本地连接的好处,但是您可以共享初始化/断开连接功能。
tearDown
如果您真的想unsafe和C 一起玩,可以将以下代码用作模板。
unsafe
检查/运行时.c:
// +build gc #include <runtime.h> void ·FirstDeferred(void* foo) { foo = g->defer->fn; FLUSH(&foo); }
inspect / inspect.go
package inspect import "unsafe" func FirstDeferred() unsafe.Pointer
defer.go
package main import "defer/inspect" func f(a, b int) { println("deferred f(", a, b, ")") } func main() { defer f(1, 2) println( inspect.FirstDeferred() ) }
该代码(基于this)使您可以访问当前的go例程(g),从而可以访问其defer属性。因此,您应该能够访问该函数的指针并将其包装在go中FuncVal并返回它。
g
FuncVal