defer、panic、recover

defer(延遲執行語句)

多個延遲執行語句的處理順序函數

package main
import (
    "fmt"
)
func main() {
    fmt.Println("defer begin")
    // 將defer放入延遲調用棧
    defer fmt.Println(1)
    defer fmt.Println(2)
    // 最後一個放入, 位於棧頂, 最早調用
    defer fmt.Println(3)
    fmt.Println("defer end")
}

結果分析以下:spa

  • 代碼的延遲順序與最終的執行順序是反向的。
  • 延遲調用是在 defer 所在函數結束時進行,函數結束能夠是正常返回時,也能夠是發生宕機時。

使用延遲執行語句在函數退出時釋放資源

處理業務或邏輯中涉及成對的操做是一件比較煩瑣的事情,好比打開和關閉文件、接收請求和回覆請求、加鎖和解鎖等。在這些操做中,最容易忽略的就是在每一個函數退出處正確地釋放和關閉資源。
defer 語句正好是在函數退出時執行的語句,因此使用 defer 能很是方便地處理資源釋放問題。code

 

panic——程序終止運行

package main
func main() {
    panic("crash")
}

在宕機時觸發延遲執行語句

當 panic() 觸發的宕機發生時,panic() 後面的代碼將不會被運行,可是在 panic() 函數前面已經運行過的 defer 語句依然會在宕機發生時發生做用,參考下面代碼blog

package main
import "fmt"
func main() {
    defer fmt.Println("宕機後要作的事情1")
    defer fmt.Println("宕機後要作的事情2")
    panic("宕機")
}

輸出結果爲:資源

宕機後要作的事情2
宕機後要作的事情1
panic: 宕機

goroutine 1 [running]:
main.main()
    F:/src/tester/main.go:8 +0x1a4

 

recover

不管是代碼運行錯誤由 Runtime 層拋出的 panic 崩潰,仍是主動觸發的 panic 崩潰,均可以配合 defer 和 recover 實現錯誤捕捉和恢復,讓代碼在發生崩潰後容許繼續運行。class

defer func() {
    if r:= recover();r != nil{
        log.Printf("Runtime error caught :%v",r)
    }
}()

foo()
相關文章
相關標籤/搜索