在函数中,我们需要创建资源(比如: 数据库连接、文件句柄、锁等)
为了在函数执行完毕后,及时释放资源,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.