掃二維碼與項目經(jīng)理溝通
我們在微信上24小時期待你的聲音
解答本文疑問/技術(shù)咨詢/運營咨詢/技術(shù)建議/互聯(lián)網(wǎng)交流
Recover 是一個Go語言的內(nèi)建函數(shù),可以讓進(jìn)入宕機(jī)流程中的 goroutine 恢復(fù)過來,recover 僅在延遲函數(shù) defer 中有效,在正常的執(zhí)行過程中,調(diào)用 recover 會返回 nil 并且沒有其他任何效果,如果當(dāng)前的 goroutine 陷入恐慌,調(diào)用 recover 可以捕獲到 panic 的輸入值,并且恢復(fù)正常的執(zhí)行。

晉中網(wǎng)站建設(shè)公司成都創(chuàng)新互聯(lián),晉中網(wǎng)站設(shè)計制作,有大型網(wǎng)站制作公司豐富經(jīng)驗。已為晉中成百上千提供企業(yè)網(wǎng)站建設(shè)服務(wù)。企業(yè)網(wǎng)站搭建\外貿(mào)網(wǎng)站制作要多少錢,請找那個售后服務(wù)好的晉中做網(wǎng)站的公司定做!
通常來說,不應(yīng)該對進(jìn)入 panic 宕機(jī)的程序做任何處理,但有時,需要我們可以從宕機(jī)中恢復(fù),至少我們可以在程序崩潰前,做一些操作,舉個例子,當(dāng) web 服務(wù)器遇到不可預(yù)料的嚴(yán)重問題時,在崩潰前應(yīng)該將所有的連接關(guān)閉,如果不做任何處理,會使得客戶端一直處于等待狀態(tài),如果 web 服務(wù)器還在開發(fā)階段,服務(wù)器甚至可以將異常信息反饋到客戶端,幫助調(diào)試。
在其他語言里,宕機(jī)往往以異常的形式存在,底層拋出異常,上層邏輯通過 try/catch 機(jī)制捕獲異常,沒有被捕獲的嚴(yán)重異常會導(dǎo)致宕機(jī),捕獲的異??梢员缓雎裕尨a繼續(xù)運行。
Go語言沒有異常系統(tǒng),其使用 panic 觸發(fā)宕機(jī)類似于其他語言的拋出異常,recover 的宕機(jī)恢復(fù)機(jī)制就對應(yīng)其他語言中的 try/catch 機(jī)制。
下面的代碼實現(xiàn)了 ProtectRun() 函數(shù),該函數(shù)傳入一個匿名函數(shù)或閉包后的執(zhí)行函數(shù),當(dāng)傳入函數(shù)以任何形式發(fā)生 panic 崩潰后,可以將崩潰發(fā)生的錯誤打印出來,同時允許后面的代碼繼續(xù)運行,不會造成整個進(jìn)程的崩潰。
保護(hù)運行函數(shù):
package main
import (
"fmt"
"runtime"
)
// 崩潰時需要傳遞的上下文信息
type panicContext struct {
function string // 所在函數(shù)
}
// 保護(hù)方式允許一個函數(shù)
func ProtectRun(entry func()) {
// 延遲處理的函數(shù)
defer func() {
// 發(fā)生宕機(jī)時,獲取panic傳遞的上下文并打印
err := recover()
switch err.(type) {
case runtime.Error: // 運行時錯誤
fmt.Println("runtime error:", err)
default: // 非運行時錯誤
fmt.Println("error:", err)
}
}()
entry()
}
func main() {
fmt.Println("運行前")
// 允許一段手動觸發(fā)的錯誤
ProtectRun(func() {
fmt.Println("手動宕機(jī)前")
// 使用panic傳遞上下文
panic(&panicContext{
"手動觸發(fā)panic",
})
fmt.Println("手動宕機(jī)后")
})
// 故意造成空指針訪問錯誤
ProtectRun(func() {
fmt.Println("賦值宕機(jī)前")
var a *int
*a = 1
fmt.Println("賦值宕機(jī)后")
})
fmt.Println("運行后")
}
代碼輸出結(jié)果:
運行前
手動宕機(jī)前
error: &{手動觸發(fā)panic}
賦值宕機(jī)前
runtime error: runtime error: invalid memory address or nil pointer dereference
運行后
對代碼的說明:
panic 和 recover 的組合有如下特性:
雖然 panic/recover 能模擬其他語言的異常機(jī)制,但并不建議在編寫普通函數(shù)時也經(jīng)常性使用這種特性。
在 panic 觸發(fā)的 defer 函數(shù)內(nèi),可以繼續(xù)調(diào)用 panic,進(jìn)一步將錯誤外拋,直到程序整體崩潰。
如果想在捕獲錯誤時設(shè)置當(dāng)前函數(shù)的返回值,可以對返回值使用命名返回值方式直接進(jìn)行設(shè)置。

我們在微信上24小時期待你的聲音
解答本文疑問/技術(shù)咨詢/運營咨詢/技術(shù)建議/互聯(lián)網(wǎng)交流