分享
defer的执行顺序与时机
moonbamboo · · 4397 次点击 · · 开始浏览这是一个创建于 的文章,其中的信息可能已经有所发展或是发生改变。
我们知道defer会在函数结束时执行,那么首先思考两个问题:
- 如果有多个defer,执行顺序是怎样的?
- 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的原因,还涉及到函数匿名返回值与命名返回值的差异,以后再单独分析。
结论
- defer的执行顺序为:后defer的先执行。
- defer的执行顺序在return之后,但是在返回值返回给调用方之前,所以使用defer可以达到修改返回值的目的。
有疑问加站长微信联系(非本文作者)
入群交流(和以上内容无关):加入Go大咖交流群,或添加微信:liuxiaoyan-s 备注:入群;或加QQ群:692541889
关注微信4397 次点击
添加一条新回复
(您需要 后才能回复 没有账号 ?)
- 请尽量让自己的回复能够对别人有帮助
- 支持 Markdown 格式, **粗体**、~~删除线~~、
`单行代码` - 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
- 图片支持拖拽、截图粘贴等方式上传
收入到我管理的专栏 新建专栏
我们知道defer会在函数结束时执行,那么首先思考两个问题:
- 如果有多个defer,执行顺序是怎样的?
- 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的原因,还涉及到函数匿名返回值与命名返回值的差异,以后再单独分析。
结论
- defer的执行顺序为:后defer的先执行。
- defer的执行顺序在return之后,但是在返回值返回给调用方之前,所以使用defer可以达到修改返回值的目的。