defer
defer是go提供的一种延迟执行机制。
后进先出原则
当执行defer时,会将对应的函数压入栈中,在函数返回或者panic异常结束时,go会从栈中取出延迟函数执行。
func main(){
defer fmt.Println("1")
defer fmt.Println("2")
defer fmt.Println("3")
fmt.Println("hello")
}
打印结果为
hello
3
2
1
立即解析原则
i := 1
defer fmt.Printf("first is %d\n", i) //1
i = 2
fmt.Printf("current is %d\n", i)//2
当 defer 以闭包的方式引用外部变量时,则会在延迟函数真正执行的时候,根据整个上下文确定当前的值
可修改返回值
func main() {
fmt.Println(test())
}
func test() (i int) {
defer func() { i++ }()
return 1
}
打印结果是2
panic
panic是一个严重错误机制,它会导致程序终止,并依次逆序执行 panic 所在函数可能存在的 defer 函数列表,然后返回该函数的调用方。
recover 内置函数可用于捕获 panic,重新恢复程序正常执行流程,但是 recover 函数只有在 defer 内部使用才有效
func main() {
err := panicAndReturnErr()
if err != nil{
fmt.Printf("err is %+v\n", err)
}
fmt.Println("returned normally from panicAndReturnErr")
}
func panicAndReturnErr() (err error){
defer func() {//如果defer内有recover,则从 panic 中恢复,不会终止程序
if e := recover(); e != nil {//error occur!
// 打印栈信息
buf := make([]byte, 1024)
buf = buf[:runtime.Stack(buf, false)]
err = fmt.Errorf("[PANIC]%v\n%s\n", e, buf)
}
}()
fmt.Println("panic begin")
panic("error occur!")//开始执行defer函数
fmt.Println("panic over")
return nil
}