该文章始发于公众号【迈莫coding】
目录
- defer执行时机
- defer执行顺序
- defer与return谁先谁后
- 函数包含多个Panic,defer中recover处理那个Panic
- 函数返回值遇到defer
- defer遇到Panic
- defer遇到Panic,但是并不捕获异常的情况
- defer遇到Panic,并捕获异常
- 练习:defer面试题
- 闲聊
- 欢迎加入我的公众号【迈莫coding】 一起pk大厂
defer执行时机
return
语句执行完之后,如果有defer
语句,再执行defer
语句- 发生
Panic
,也会触发defer
执行
defer执行顺序
多个defer出现时,会以"先进后出,后进先出"的规则来执行,类似于数据结构中栈的执行顺序.
示例:
package main import "fmt" func main() { defer func(){ fmt.Println("A") }() defer func(){ fmt.Println("B") } defer func(){ fmt.Println("C") }
结果:
C B A
defer与return谁先谁后
示例代码
package main import "fmt" func deferFunc() { fmt.Println("defer func") } func returnFunc() int { fmt.Println("return func") return 1 } func returnAndDefer() int { defer deferFunc() return returnFunc() } func main() { returnAndDefer
结果
return func defer func
结论
一个函数中即有return语句,也有defer语句,先执行return语句,后执行defer语句
函数包含多个Panic,defer中recover处理那个Panic
示例
package main import "fmt" func main() { defer func() { if err := recover(); err != nil { fmt.Println(err) }else { fmt.Println("fail") } }() defer func() { panic("defer panic") }() panic("main panic")
结果
defer panic
结论
只有最后一个panic,可以被recover捕获到.
函数返回值遇到defer
示例
package main import "fmt" func deferFunc() (t int) { // t初始化为0,并且作用域为该函数全域 defer func() { t = t * 10 }() return 1 } func main() { fmt.Println(deferFunc())
结果
10
结论
当调用deferFunc()函数时,本应该返回值1,但函数中还有defer语句,所以在return语句之后,又被defer的匿名函数func函数执行,所以t=t*10被执行。因此返回值为10.
defer遇到Panic
defer遇到Panic,但是并不捕获异常的情况
示例
package main import "fmt" func defer_panic() { defer func() { fmt.Println("defer: panic() 执行1") }() defer func() { fmt.Println("defer: panic() 执行2") } panic("发生异常") fmt.Println("该条语句无法执行") } func main() { defer_panic() fmt.Println("main函数执行完成")
结果
defer: panic() 执行2 defer: panic() 执行1 panic: 发生异常 // 异常信息...
defer遇到Panic,但捕获异常的情况
示例
package main import "fmt" func defer_panic() { defer func() { fmt.Println("defer: panic() 执行1") if err := recover(); err != nil { fmt.Println(err) } }() defer func() { fmt.Println("defer: panic() 执行2") } panic("发生异常") fmt.Println("该条语句无法执行") } func main() { defer_panic() fmt.Println("main函数执行完成")
结果
defer: panic() 执行2 defer: panic() 执行1 发生异常 main函数执行完成
练习:defer面试题
- 下面代码输出什么?
package main import "fmt" func main() { var name = "zhangsan" fmt.Println(name) defer fmt.Println(name) name = "lisa" fmt.Println(name) defer fmt.Println(name)
考点
defer和函数组合调⽤方式
结果
zhangsan lisa lisa zhangsan
- 程序运行结果
示例
package main import ( "fmt" ) func main() { defer_call() } func defer_call() { defer func() { fmt.Println("迈") }() defer func() { fmt.Println("莫") }() defer func() { fmt.Println("coding") }() }
考点
defer和函数组合调⽤方式
结果
coding 莫 迈
- 下面代码输出什么?
示例
package main import "fmt" func DeferFunc1(i int) (t int) { t = i defer func() { t += 3 }() return t } func main() { fmt.Println(DeferFunc1(1)) }
考点
defer和函数组合调⽤方式
结果
4
执行过程
1. 将返回值t赋值为行参i,t = 1 2. 执行return语句,将t 赋值给t 3. 执行defer语句,t + 3 = 4 4. 返回值4
- 下面代码输出什么?
示例
package main import "fmt" func DeferFunc2(i int) int { t := i defer func() { t += 3 }() return t } func main() { fmt.Println(DeferFunc2(1)) }
考点
defer和函数组合调⽤方式
结果
1
执行过程
1. 创建变量t并将其赋值为i的值,t = 1 2. 执行return语句,注意这里是将t赋值给返回值,此时返回值为1(这个返回值并不是t) 3.执行defer语句,t = t + 3 = 4 4. 函数返回值1
- 下面代码输出什么?
示例
package main import "fmt" func DeferFunc3(i int) (t int) { defer func() { t += i }() return 2 } func main() { fmt.Println(DeferFunc3(1))
考点
defer和函数组合调⽤方式
结果
3
执行过程
1. 首先将t赋值为2 2. 执行defer语句,t = t + 1 = 3 3. 函数返回值3
- 下面代码输出什么?
示例
package main import "fmt" func DeferFunc4() (t int) { defer func(i int) { fmt.Println(i) fmt.Println(t) }(t) t = 1 return 2 } func main() { DeferFunc4() }
考点
defer和函数组合调⽤方式
结果
0 2
执行过程
1. 初始化返回值t为零值 0 2. 首先执行defer的第一步,赋值defer中的func入参t为0 3. 执行defer的第二步,将defer压栈 4. 将t赋值为1 5. 执行return语句,将返回值t赋值为2 6. 执行defer的第三步,出栈并执行 7. 因为在入栈时defer执行的func的入参已经赋值了,此时它作为的是一个形式参数,所以打印为0;相对应的因为最后已经将t的值修改为2,所以再打印一个2
闲聊
- 读完文章,自己是不是和defer的cp率又提高了
- 我是迈莫,欢迎大家和我交流
欢迎加入我的公众号【迈莫coding】 一起pk大厂
- 迈莫coding欢迎客官的到来
有疑问加站长微信联系(非本文作者)