1.执行顺序
首先看下面这个程序,写出它打印的结果
package main
import (
"fmt"
)
func main() {
d()
}
func d() {
defer func() { fmt.Println("打印前") }()
defer func() { fmt.Println("打印中") }()
defer func() { fmt.Println("打印后") }()
panic("触发异常")
}
defer 是后进先出。
panic 需要等defer 结束后才会向上传递。 出现panic的时候,会先按照defer的后入先出的顺序执行,最后才会执行panic。所以最终的打印结果:
打印后
打印中
打印前
panic: 触发异常
2.内置函数
再看一看这个程序
func calc(index string, a, b int) int {
ret := a + b
fmt.Println(index, a, b, ret)
return ret
}
func main() {
a := 1
b := 2
defer calc("1", a, calc("10", a, b))
a = 0
defer calc("2", a, calc("20", a, b))
b = 1
}
最终的输出会是什么呢,如果按照defer的思想后进显出是不是到第2个defer完成的时候第一个defer中的a为0,b为1呢,虽然defer是后进先出,但defer表达式中的函数确是顺序执行的,所以最先被调用calc(“10”,1,2)>10,1,2,3 执行index:2时,与之前一样,需要先调用calc(“20”,0,2)>20,0,2,2 执行到b=1时候开始调用,index:2==>calc(“2”,0,2)>2,0,2,2 最后执行index:1>calc(“1”,1,3)==>1,1,3,4
所以最后输出的结果是:
10 1 2 3
20 0 2 2
2 0 2 2
1 1 3 4
3.作用域
最后一个题:
func main() {
println(DeferFunc1(1))
println(DeferFunc2(1))
println(DeferFunc3(1))
}
func DeferFunc1(i int) (t int) {
t = i
defer func() {
t += 3
}()
return t
}
func DeferFunc2(i int) int {
t := i
defer func() {
t += 3
}()
return t
}
func DeferFunc3(i int) (t int) {
defer func() {
t += i
}()
return 2
}
根据上面的粒子,这里就是调用了三个函数,而且defer在函数里面,是否就是按照程序的执行思路输出 4,4,2 呢,很显然没有那么简单,需要明确一点是defer需要在函数结束前执行。 函数返回值名字会在函数起始处被初始化为对应类型的零值并且作用域为整个函数 DeferFunc1有函数返回值t作用域为整个函数,在return之前defer会被执行,所以t会被修改,返回4; DeferFunc2函数中t的作用域为函数,返回1; DeferFunc3返回3,结果就是4,1,3
这上面的三道题,是否加深了小伙伴们对defer的理解呢。