如果❤️我的文章有帮助,欢迎点赞、关注。这是对我继续技术创作最大的鼓励。更多往期文章在我的个人博客
defer 英语中有延迟
、押后
,而”人如其名” —— Go语言的 defer 语句也会将其后面跟随的语句进行延迟处理。
具体是怎么个延迟法?我们先来看个例子:
函数return之后、结束前被执行
func returnAndDefer() int {
defer func() {
fmt.Println("defer func called")
}()
return func() int {
fmt.Println("return func called")
return 0
}()
}
returnAndDefer
函数的执行会使标准输出上打印出
return func called
defer func called
函数 returnAndDefer
的功能是打印出 defer func called
、return func called
两条语句。
我们通过观察它们打印顺序得出 defer
/return
被执行顺序。
func(){}()
为Go语言匿名函数写法,这里就不是主题就先不纠结。
请注意returnAndDefer
函数中的倒数第二条语句defer func() {}
。
当这条defer语句被执行的时候,其中的 defer func called
匿名方法并不会被立即执行。
它的确切的执行时机是在其所属的函数执行即将结束
的那个时刻,也就是returnAndDefer
函数return
之后,函数结束之前。
也就是说,在returnAndDefer函数真正结束执行的前一刻,fmt.Println("defer func called")
才会被执行。
这也是defer语句被如此命名的原因。语句 defer 在 函数即将结束时执行
的特性非常适合 读取完文件内容后一定要关闭
、查询完数据库后关系数据库链接
等场景
defer语句可以保证在函数将结果返回给调用方之前,那个之前占用的资源一定会被被销毁,是一种非常便捷和有效的保险措施。
学费的童鞋不妨做下下面的输出
func testReturnAndDefer()(t int){
defer func(){
t = t *10
}()
return 1
}
testReturnAndDefer()
本应的返回值是1,但是在return
之后,又被defer的匿名函数
执行。
所以t=t*10被执行,最后testReturnAndDefer()
返回结果为10
多个 defer, 后进先出
多个 defer
出现的时候,它就是一个后进先出
的 堆栈
关系,举个例子:
func manyDefer() {
defer func() {
fmt.Print(1)
}()
defer func() {
fmt.Print(2)
}()
defer func() {
fmt.Print(3)
}()
defer func() {
fmt.Print(4)
}()
}
manyDefer
函数的执行会使标准输出上打印出4321
,哪怕是下方遍历打印
之后的输出也是一样
func manyDeferV2() {
for i := 1; i < 5; i++ {
defer fmt.Print(i)
}
}
练习题
所谓光说不练假把式,各有勇士把答案打在留言上
func manyDeferV3() {
for i := 1; i < 5; i++ {
defer func() {
fmt.Print(i)
}()
}
fmt.Println()
for i := 1; i < 5; i++ {
defer func(n int) {
fmt.Print(n)
}(i)
}
}
完整代码
package main
import (
"fmt"
)
func main() {
returnAndDefer()
fmt.Println(testReturnAndDefer())
manyDefer()
manyDeferV2()
fmt.Println()
manyDeferV3()
}
func returnAndDefer() int {
defer func() {
fmt.Println("defer func called")
}()
return func() int {
fmt.Println("return func called")
return 0
}()
}
func testReturnAndDefer()(t int){ //t初始化0,作用域为该函数全域
defer func(){
t = t *10
}()
return 1
}
func manyDefer() {
defer func() {
fmt.Print(1)
}()
defer func() {
fmt.Print(2)
}()
defer func() {
fmt.Print(3)
}()
defer func() {
fmt.Print(4)
}()
}
func manyDeferV2() {
for i := 1; i < 5; i++ {
defer fmt.Print(i)
}
}
func manyDeferV3() {
for i := 1; i < 5; i++ {
defer func() {
fmt.Print(i)
}()
}
fmt.Println()
for i := 1; i < 5; i++ {
defer func(n int) {
fmt.Print(n)
}(i)
}
}