如果❤️我的文章有帮助,欢迎点赞、关注。这是对我继续技术创作最大的鼓励。更多往期文章在我的个人博客
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)
	}
}
