在函数中,我们需要创建资源(比如: 数据库连接、文件句柄、锁等)

为了在函数执行完毕后,及时释放资源,Go的设计者提供"defer"(延时机制)

​1. 当go执行到一个defer后的语句时,会将defer后的语句先压入到一个栈中,然后继续执行函数下一个语句

2. 当函数其他命令执行完毕后,在从defer栈中,依次从栈顶去除语句执行
   (注: 遵守栈 先进后出的机制来输出)

3. 在defer将语句放入到栈中时,也会将相关的值拷贝同时入栈

案例1

package main

import "fmt"

func sum(n1 int,n2 int) int{

	//将执行到defer时,会将defer后面的语句,压入到栈内存中(defer栈),暂时不执行
	//当函数执行完毕后,再从defer栈,按照先进后出的方式,出栈,然后执行

	defer fmt.Println("ok1 n1=",n1)
	defer fmt.Println("ok2 n2=",n2)

	res := n1 + n2

	fmt.Println("ok3 res",res)

	return res
}

func main(){
	res := sum(10,20)
	fmt.Println("res=",res)
}

返回

ok3 res 30
ok2 n2= 20
ok1 n1= 10
res= 30

#n1、n2被压栈了,所以ok3 res 先出
#函数结束后 n1、n2弹栈输出
#完事了再输出res=30

案例2

package main

 import (
     "fmt"
 )

 func main() {
     defer_call()
 }

func defer_call() {
    defer func() { fmt.Println("打印前") }()
    defer func() { fmt.Println("打印中") }()
    defer func() { fmt.Println("打印后") }()
    panic("触发异常")       //抛出异常,停止程序
}

返回

打印后
打印中
打印前
panic: 触发异常

defer 的执行顺序是后进先出。当出现 panic 语句的时候,会先按照 defer 的后进先出的顺序执行,最后才会执行panic

案例3

package main

import (
	"errors"
	"fmt"
)

func main() {
	fmt.Println("Enter function main.")
	defer func(){
		fmt.Println("Enter defer function.")
		if p := recover(); p != nil {
			fmt.Printf("panic: %s\n", p)
		}
		fmt.Println("Exit defer function.")
	}()
	
	// 引发 panic。
	panic(errors.New("something wrong"))
	fmt.Println("Exit function main.")
}

返回

Enter function main.
Enter defer function.
panic: something wrong
Exit defer function.