我怎样才能得到延期功能的参考? [英] How can I get a reference to a defer function?
问题描述
本文指出:延迟声明将函数调用推送到清单。我想知道是否可以从我的程序中的其他位置访问该列表中的元素,然后调用它们?我可以多次调用它们吗?我假设我有一个引用推迟行为的函数(如果有帮助的话)。
所以,下面是我想要做的一个简短示例:
func main {
doStuff = func(){
//打开数据库连接
//写入临时文件
//等等...
推迟func(){
//关闭数据库连接
//删除临时文件
//等等...
}()
}
AwesomeApplication(doStuff)
}
func AwesomeApplication(doStuff func() ){
//现在,我可以在`doStuff`中获得对延迟函数的引用吗?
//不,我不能只是在某处传递
//用`doStuff`来定义延迟函数。把这看作是我想要满足的好奇心,
//不是真正的用例。
存储的 defer
调用完全是特定于实现的,所以您没有可靠的方法来访问此列表。 1 , 2 可以在中找到* g编译器系列的实现细节(尽管有点旧) Russ Cox的研究博客。
递延函数与当前goroutine相关联( )和
(在* g系列的情况下)由当前堆栈指针标识。如果当前的堆栈框架匹配
堆栈框架存储在最顶端的 Defer
条目中,则调用此函数。
有了这些知识,使用cgo访问延迟函数列表就成为可能。
您需要知道的是
- 当前堆栈指针
- 函数的地址
- 当前goroutine
然而,我不建议使用这个。
您描述的用例的一般解决方案是使用这样的函数:
func setupRoutines ()(setUp,tearDown func()){
//存储数据库连接对象和这样的
返回func(){/ *连接数据库和这样的* /},func(){ / * close db and such * /}
}
在您的代码中, tearDown
函数,它将使用 defer
来调用。
这样,您仍然可以获得所有数据库连接和本地数据库的奖励,但您可以共享初始化/断开连接功能。
小提琴与
一起玩如果您真的有兴趣玩弄不安全
和C,你可以使用下面的代码作为模板。
inspect / runtime.c:
// + build gc
#include< runtime.h>
void·FirstDeferred(void * foo){
foo = g-> defer-> fn;
FLUSH(& foo);
inspect / inspect.go
包检查
导入不安全
func FirstDeferred()unsafe.Pointer
defer.go
package main
importdefer / inspect
func f(a,b int){
println(deferred f(,a,b,) )
func main(){
defer f(1,2)
println(inspect.FirstDeferred())
}
这段代码(基于这个)可以访问当前的例程( g
),因此
推迟
属性。因此,您应该能够访问指向函数
的指针,并将其包装到 FuncVal
中并返回。
This article states: "A defer statement pushes a function call onto a list." I'm wondering if I can access the elements in that list from another place in my program and then invoke them? Can I invoke them multiple times? I'm assuming that I have a reference to the function that has defer behavior (if that helps).
So, here's a short example of what I want to do:
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.
}
The 'list' where to defer
calls are stored are fully implementation specific so you have no reliable way of getting to this list.1,2 The implementation details for the *g compiler family (albeit a bit older) can be found in Russ Cox' research blog.
Deferred functions are associated with the current goroutine (g->Defer
) and
(in case of *g family) identified by the current stack pointer. If the current stack frame matches
the stack frame stored in the topmost Defer
entry, this function is called.
With this knowledge it is possible to access the list of deferred functions using cgo. You need to know
- the current stack pointer
- the address of the function
- the current goroutine
However, I don't recommend using this. A general solution for the use case you're describing would be to have a function like this:
func setupRoutines() (setUp, tearDown func()) {
// store db connection object and such
return func() { /* connect db and such */ }, func() { /* close db and such */ }
}
In your code you could then share the tearDown
function, which would be called using defer
.
This way you still have the bonus of having all your database connections and such local but you're
able to share the initialization/disconnect functions.
Fiddle to play with
If you're really interested in playing around with unsafe
and C, you can use the following code as a template.
inspect/runtime.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 code (based on this) gives you access to the current go routine (g
) and therefore
the defer
attribute of it. Therefore you should be able to access the pointer to the function
and wrap it in a go FuncVal
and return it.
这篇关于我怎样才能得到延期功能的参考?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!