golang defer用法

func main() {
    bigSlowOperation()
}

func bigSlowOperation() {
    defer trace("bigSlowOperation")() // don't forget the extra parentheses
    // ...lots of work...
    time.Sleep(1 * time.Second) // simulate slow
    //operation by sleeping
}
func trace(msg string) func() {
    start := time.Now()
    log.Printf("enter %s", msg)
    return func() {
        log.Printf("exit %s (%s)", msg,time.Since(start))
    }
}

上述代码执行的结果是
2021/07/20 21:48:44 enter bigSlowOperation
2021/07/20 21:48:45 exit bigSlowOperation (1.0313889s)
问题:defer后面的函数不是延迟执行吗 为啥先执行trace(“bigSlowOperation”)?

最佳答案

个人理解:你可以试验一下,defer后面的表达式有返回是 匿名函数返回的是常规变量 或者 什么也不返回 ,执行的情况是不一样的。

只有 返回的是常规变量 或者 什么也不返回 符合defer的完全延迟执行的特性,defer延迟执行的是这个函数体。defer后面的表达式如果再返回一个匿名函数的话,return的这个匿名函数体是被延迟执行的,但这个表达式内的return之前的变量等会被立即调用。

贴一个链接你看看:mp.weixin.qq.com/s/5xeAOYi3OoxCEPe...

3年前 评论
讨论数量: 3

你只需要在调用普通函数或方法前加上关键字defer,就完成了defer所需要的语法。当执行到该条语句时,函数和参数表达式得到计算,但直到包含该defer语句的函数执行完毕时,defer后的函数才会被执行,不论包含defer语句的函数是通过return正常结束,还是由于panic导致的异常结束。你可以在一个函数中执行多条defer语句,它们的执行顺序与声明顺序相反。

这个是我从Go圣经里引用过来的,可以解释你的问题。

3年前 评论
iBebe (楼主) 3年前

我的理解: 是因为这里延迟的方法不是trace(msg string)方法. 而是trace(msg string)方法返回的方法.仔细一点可以看到后面的注释为不要忘记额外的括号.结合trace(msg string)方法的返回值为func()来看 .这里的逻辑就是延迟执行trace(msg string)方法产生的无参方法.所以说trace方法是正常执行的(不是等到外面的函数执行完在执行).也就是说输出就是会先输出enter xxx,然后在延时一秒后在输出exit xxx

3年前 评论

个人理解:你可以试验一下,defer后面的表达式有返回是 匿名函数返回的是常规变量 或者 什么也不返回 ,执行的情况是不一样的。

只有 返回的是常规变量 或者 什么也不返回 符合defer的完全延迟执行的特性,defer延迟执行的是这个函数体。defer后面的表达式如果再返回一个匿名函数的话,return的这个匿名函数体是被延迟执行的,但这个表达式内的return之前的变量等会被立即调用。

贴一个链接你看看:mp.weixin.qq.com/s/5xeAOYi3OoxCEPe...

3年前 评论

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!