本文指出:"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.
}
Run Code Online (Sandbox Code Playgroud)
nem*_*emo 11
defer
存储调用位置的"列表" 是完全特定于实现的,因此您没有可靠的方法来访问此列表.1,2为*G编译器家族中的实现细节(虽然有点老),可以发现在拉斯考克斯的研究博客.
延迟函数与g->Defer
当前堆栈指针标识的当前goroutine()和(在*g系列的情况下)相关联.如果当前堆栈帧与存储在最顶层Defer
条目中的堆栈帧匹配,则调用此函数.
有了这些知识,就可以使用cgo访问延迟函数列表.你得知道
但是,我不建议使用它.您正在描述的用例的一般解决方案是具有如下函数:
func setupRoutines() (setUp, tearDown func()) {
// store db connection object and such
return func() { /* connect db and such */ }, func() { /* close db and such */ }
}
Run Code Online (Sandbox Code Playgroud)
在您的代码中,您可以共享该tearDown
函数,该函数将被调用defer
.这样你仍然可以获得所有数据库连接和本地连接,但是你可以共享初始化/断开连接功能.
如果您真的对使用unsafe
C和C 感兴趣,可以使用以下代码作为模板.
检查/ runtime.c:
// +build gc
#include <runtime.h>
void ·FirstDeferred(void* foo) {
foo = g->defer->fn;
FLUSH(&foo);
}
Run Code Online (Sandbox Code Playgroud)
检查/ inspect.go
package inspect
import "unsafe"
func FirstDeferred() unsafe.Pointer
Run Code Online (Sandbox Code Playgroud)
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() )
}
Run Code Online (Sandbox Code Playgroud)
此代码(基于此)使您可以访问当前的go例程(g
),从而访问defer
它的属性.因此,您应该能够访问该函数的指针并将其包装在一起FuncVal
并返回它.
归档时间: |
|
查看次数: |
159 次 |
最近记录: |