defer的执行顺序与时机

moonbamboo · · 3871 次点击 · · 开始浏览    
这是一个创建于 的文章,其中的信息可能已经有所发展或是发生改变。

我们知道defer会在函数结束时执行,那么首先思考两个问题:

  1. 如果有多个defer,执行顺序是怎样的?
  2. defer是在return之前还是之后执行的?如果defer执行的内容对返回值进行了修改,return结果是否会改变?

多个defer的执行顺序

通过下面这个个例子,我们看下defer的执行顺序:

package main

import (
    "fmt"
)

func main() {
    defer fmt.Println("main defer1")
    test()
    defer fmt.Println("main defer2")
}

func test() () {
    defer func() {
        fmt.Println("test defer1")
    }()
    defer func() {
        fmt.Println("test defer2")
    }()
}

执行结果为:

test defer2
test defer1
main defer2
main defer1

我们发现defer就像一个LIFO的栈,后defer的会先执行,且在函数退出时才会执行。

defer与return的执行顺序

首先看个例子:

package main

import (
    "fmt"
)

func main() {
    ret := test()
    fmt.Println("test return:", ret)
}

func test() ( int) {
    var i int

    defer func() {
        i++        //defer里面对i增1
        fmt.Println("test defer, i = ", i)
    }()

    return i
}

执行结果为:

test defer, i =  1
test return: 0

test函数的返回值为0,defer里面的i++操作好像对返回值并没有什么影响。
这是否表示“return i”执行结束以后才执行defer呢?
非也!再看下面的例子:

package main

import (
    "fmt"
)

func main() {
    ret := test()
    fmt.Println("test return:", ret)
}

//返回值改为命名返回值
func test() (i int) {
    //var i int

    defer func() {
        i++
        fmt.Println("test defer, i = ", i)
    }()

    return i
}

执行结果为:

test defer, i =  1
test return: 1

这次test函数的返回值变成了1,defer里面的“i++"修改了返回值。所以defer的执行时机应该是return之后,且返回值返回给调用方之前。
至于第一个例子中test函数返回值不是1的原因,还涉及到函数匿名返回值与命名返回值的差异,以后再单独分析。

结论

  1. defer的执行顺序为:后defer的先执行。
  2. defer的执行顺序在return之后,但是在返回值返回给调用方之前,所以使用defer可以达到修改返回值的目的。

有疑问加站长微信联系(非本文作者)

本文来自:Segmentfault

感谢作者:moonbamboo

查看原文:defer的执行顺序与时机

入群交流(和以上内容无关):加入Go大咖交流群,或添加微信:liuxiaoyan-s 备注:入群;或加QQ群:692541889

3871 次点击  
加入收藏 微博
暂无回复
添加一条新回复 (您需要 登录 后才能回复 没有账号 ?)
  • 请尽量让自己的回复能够对别人有帮助
  • 支持 Markdown 格式, **粗体**、~~删除线~~、`单行代码`
  • 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
  • 图片支持拖拽、截图粘贴等方式上传