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

为了在函数执行完毕后,及时释放资源,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.