Golang中使用recover捕獲panic的操作及遇到的一個坑


說明

  本文介紹一下使用recover捕獲panic的操作及遇到的一個坑。

使用recover捕獲panic

  正常情況下,發生panic的函數會導致程序異常退出,我們可以使用defer語句在另外一個函數中捕獲到當前函數panic的error並做相應的邏輯處理:

package test1

import (
    "fmt"
    "testing"
)

func TestRecover(t *testing.T) {

    handleSth()

}

// 返回的函數
func sendResponse(err string) {
    // 有錯誤返回錯誤信息
    if err != "" {
        fmt.Println("發生異常:", err)
    } else {
        println("成功sendResponse")
    }
}

// 專門用於捕獲異常的
func rec1() {
    err := recover()
    // 注意這里捕獲到的err是一個interface,需要與nil做比較
    if err != nil {
        sendResponse(err.(string))
    } else {
        sendResponse("")
    }
}

// 業務代碼,可能發生異常
func handleSth() {

    // 如果函數中發生了異常會被rec1()函數捕獲到
    defer rec1()
    // 模擬業務代碼中發生panic的情況
    panic("發生了異常...")

}

遇到的問題

正確的方式

  正常情況下,我們使用下面的方式去捕獲panic:

package test1

import (
    "fmt"
    "testing"
)

func rec1() {
    err :=  recover()
    if err != nil{
        fmt.Println("err: ", err)
    }
}

func TestRecover(t *testing.T) {

    // 正確的捕獲方式
    defer rec1()

    panic("TestRecover raises error!")
}

錯誤的方式

  下面這種方式捕獲不到panic:

package test1

import (
    "fmt"
    "testing"
)

func rec1() {
    err :=  recover()
    if err != nil{
        fmt.Println("err: ", err)
    }
}



func TestRecover(t *testing.T) {

    // 錯誤的捕獲方式
    defer func(){
        // 這里加一些其他的業務邏輯
rec1() }() panic("TestRecover raises error!") }

  上面這種方法其實是想在recover到panic之前再做一些業務處理,結果沒有捕獲到想要捕獲的panic會導致程序崩潰。

  看了一下相關資料,解釋應該是每一個recover應該“直接”與對應的panic配對,也就是說recover應該只能捕獲到與其同一個作用域里的panic(具體原理還需要深入學習)。

  像上面的那種寫法應該在匿名函數中寫panic才可以:

func TestRecover(t *testing.T) {
    // 錯誤的捕獲方式
    func(){
        // 這里寫一些其他的業務邏輯
        defer rec1()
        panic("TestRecover raises error!")
    }()
}

  關於Golang中defer、panic與recover相關說明的參考:https://huoyingwhw.com/golangGuide/%E5%9F%BA%E7%A1%80/4/#82-defer


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM