深入理解Go語(yǔ)言中defer和panic的執(zhí)行順序
簡(jiǎn)介
在 Go 語(yǔ)言中,defer
和 panic
的執(zhí)行順序是一個(gè)重要的概念。本文將通過(guò)一個(gè)示例代碼來(lái)詳細(xì)解釋為什么 defer
中的代碼會(huì)先執(zhí)行,而 panic
的錯(cuò)誤信息稍后才輸出。
示例代碼
package main import "fmt" func mayPanic() { panic("a problem") } func main() { defer func() { if r := recover(); r != nil { fmt.Println("Recovered. Error:\n", r) } }() mayPanic() fmt.Println("After mayPanic()") }
執(zhí)行順序解釋
1. defer 的執(zhí)行機(jī)制
defer 的作用是延遲執(zhí)行一個(gè)函數(shù)調(diào)用,直到包含它的函數(shù)執(zhí)行完畢。無(wú)論函數(shù)是正常結(jié)束還是因?yàn)殄e(cuò)誤(如 panic)結(jié)束,所有被 defer 延遲的函數(shù)都會(huì)按照后進(jìn)先出(LIFO)的順序執(zhí)行。
2. panic 的傳播機(jī)制
當(dāng) panic 被觸發(fā)時(shí),Go 會(huì)立即中斷當(dāng)前函數(shù)的正常執(zhí)行流程,并開(kāi)始向上層調(diào)用棧傳播錯(cuò)誤信號(hào)。在這個(gè)過(guò)程中,Go 會(huì)依次執(zhí)行當(dāng)前函數(shù)中所有被 defer 延遲的函數(shù)。這些延遲函數(shù)可以通過(guò) recover() 捕獲并處理 panic。
3. 代碼執(zhí)行順序
(1) 執(zhí)行 main() 函數(shù)
func main() { defer func() { if r := recover(); r != nil { fmt.Println("Recovered. Error:\n", r) } }() mayPanic() // 觸發(fā) panic fmt.Println("After mayPanic()") // 這行代碼不會(huì)執(zhí)行 }
(2) 調(diào)用 mayPanic()
func mayPanic() { panic("a problem") }
panic("a problem")
被觸發(fā),程序會(huì)立即中斷當(dāng)前函數(shù)的執(zhí)行,并將 panic
信息傳播到上層調(diào)用棧。
(3) 觸發(fā) defer 延遲函數(shù)
由于 panic
的觸發(fā),Go 會(huì)開(kāi)始執(zhí)行 main()
函數(shù)中被 defer
延遲的函數(shù):
defer func() { if r := recover(); r != nil { fmt.Println("Recovered. Error:\n", r) } }()
在這個(gè)延遲函數(shù)中,recover()
被調(diào)用,捕獲了 panic
的錯(cuò)誤信息 "a problem"
,并打印出來(lái)。
(4) panic 被恢復(fù)
由于 recover()
成功捕獲了 panic
,程序的正常執(zhí)行流程得以恢復(fù)。不過(guò),panic
的傳播已經(jīng)中斷了 main()
函數(shù)的正常執(zhí)行,因此 fmt.Println("After mayPanic()")
不會(huì)執(zhí)行。
4. 輸出結(jié)果順序
按照以上執(zhí)行順序,程序的輸出如下:
Recovered. Error: a problem
為什么 defer 先執(zhí)行?
這是因?yàn)?nbsp;panic
的傳播機(jī)制會(huì)觸發(fā)所有 defer
延遲函數(shù)的執(zhí)行。defer
的設(shè)計(jì)初衷是確保某些重要的清理操作(如釋放資源、關(guān)閉文件等)能夠在函數(shù)結(jié)束時(shí)執(zhí)行,即使函數(shù)是因 panic
而異常結(jié)束的。
總結(jié)來(lái)說(shuō):
panic
會(huì)中斷當(dāng)前函數(shù)的執(zhí)行。Go 會(huì)依次執(zhí)行所有被
defer
延遲的函數(shù)。recover()
可以在延遲函數(shù)中捕獲panic
并恢復(fù)程序的執(zhí)行。
總結(jié)
通過(guò)上述代碼和解釋?zhuān)覀兛梢郧宄乜吹?nbsp;defer
和 panic
的執(zhí)行順序是由 Go 語(yǔ)言的設(shè)計(jì)規(guī)則決定的。defer
確保了清理操作的執(zhí)行,而 panic
的傳播機(jī)制允許我們?cè)谘舆t函數(shù)中捕獲并處理錯(cuò)誤。
到此這篇關(guān)于Go語(yǔ)言中defer和panic的執(zhí)行順序的文章就介紹到這了,更多相關(guān)Go語(yǔ)言 defer和panic執(zhí)行順序內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Go?gRPC教程實(shí)現(xiàn)Simple?RPC
這篇文章主要為大家介紹了Go?gRPC教程實(shí)現(xiàn)Simple?RPC示例,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-06-06Golang實(shí)現(xiàn)smtp郵件發(fā)送的示例代碼
這篇文章主要為大家詳細(xì)介紹了Golang實(shí)現(xiàn)smtp郵件發(fā)送的相關(guān)知識(shí),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2023-03-03golang int 轉(zhuǎn)float 強(qiáng)轉(zhuǎn)和高精度轉(zhuǎn)操作
這篇文章主要介紹了golang int 轉(zhuǎn)float 強(qiáng)轉(zhuǎn)和高精度轉(zhuǎn)操作,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2020-12-12Golang程序中使用Prometheus的client_golang庫(kù)
這篇文章主要介紹了Golang程序中使用Prometheus的client_golang庫(kù),Prometheus 是一個(gè)開(kāi)源的監(jiān)控和警報(bào)工具包,用于收集和處理應(yīng)用程序和系統(tǒng)的指標(biāo)數(shù)據(jù)。Prometheus 提供了多種客戶(hù)端庫(kù),可以輕松地集成到各種編程語(yǔ)言中2023-04-04