Golang中的Defer如何作用于调用者/外部函数?

7

有没有可能将defer延迟到外部函数的结尾?

// normal transaction
func dbStuff(){
    db.Begin()
    ...
    db.Commit()
}

// normal transaction w/ defer
func dbStuff(){
    db.Begin()
    defer db.Commit()
    ...
}

这是可能的吗?
// can you defer to caller / outer function?
func dbStuff(){
    db.Trans()
    ...
}

// will Commit() when dbStuff() returns
func (db Db) Trans(){
    db.Begin()
    defer db.Commit() // to caller/outer function
}
2个回答

9
根据规范,这是不可能的:
“defer”语句调用一个函数,其执行被推迟到包含它的函数返回的时刻,无论是因为包含它的函数执行了return语句、达到了其函数体的结尾,还是因为相应的goroutine正在panic。
(强调是我的)
更新:除此之外,这也不是一个好主意——Go的优点之一就是“所见即所得”。从内部函数到外部函数延迟函数会在控制流中创建“隐形”的变化。

8

这可能会有所帮助。

func main() {
    defer greet()() 
    fmt.Println("Some code here...")
}

func greet() func() {
    fmt.Println("Hello!")
    return func() { fmt.Println("Bye!") } // this will be deferred
}

输出:

Hello!
Some code here...
Bye!

参考资料:https://asanchez.dev/blog/defer-golang-on-entry/

该文章介绍了在Go语言中如何使用Defer函数来简化代码和处理错误,Defer函数可以在当前函数执行完毕后立即执行一个函数调用,它通常用于释放资源和日志记录等任务。


1
我喜欢这种方式回避了@publysher答案中的“代码隐式更改”论点,因为它在视觉上与通常的延迟和双函数调用不同。这应该是被接受的答案! - Harvastum

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接