Go的defer和recover

在 Go 語言中,deferrecover 是兩個緊密相關的關鍵字,主要用于錯誤處理資源清理。它們通常一起使用,特別是在處理panic(運行時崩潰)時,確保程序不會直接崩潰,而是能夠優雅地恢復并繼續執行。


1. defer 關鍵字

作用

defer 用于延遲執行一個函數調用,通常用于:

  • 資源釋放(如關閉文件、數據庫連接、解鎖等)。
  • 確保某些操作在函數返回前執行(即使函數提前返回或發生 panic)。

特點

  1. 延遲執行defer 語句不會立即執行,而是等到包含它的函數返回前才執行。
  2. 后進先出(LIFO):如果有多個 defer,它們會按照逆序執行(類似棧結構)。
  3. 即使 panic 也會執行defer 語句在函數 panic 時仍然會執行,這使得它非常適合用于錯誤恢復

示例

package mainimport "fmt"func main() {defer fmt.Println("1")  // 最后執行defer fmt.Println("2")  // 第二個執行fmt.Println("3")        // 最先執行
}

輸出:

3
2
1

說明:

  • defer 語句是延遲執行的,所以 fmt.Println("3") 最先執行。
  • 兩個 defer 按照逆序執行,所以 21 之前打印。

2. recover 關鍵字

作用

recover 用于捕獲 panic,防止程序直接崩潰,并允許程序繼續執行。

特點

  1. 只能在 defer 函數中使用recover 必須在 defer 調用的函數中使用,否則無效。
  2. 捕獲 panic:如果程序發生 panic,recover 可以捕獲它,并返回 panic 傳遞的值。
  3. 不會終止程序:如果 recover 成功捕獲 panic,程序不會崩潰,而是繼續執行。

示例

package mainimport "fmt"func main() {defer func() {if r := recover(); r != nil {  // 捕獲 panicfmt.Println("捕獲到 panic:", r)}}()panic("發生了一個嚴重錯誤!")  // 觸發 panicfmt.Println("這行不會執行")    // 不會執行
}

輸出:

捕獲到 panic: 發生了一個嚴重錯誤!

說明:

  • panic 會導致程序崩潰,但 defer 中的 recover 捕獲了它,程序不會退出。
  • fmt.Println("這行不會執行") 不會執行,因為 panic 已經發生,但 recover 阻止了程序崩潰。

3. defer + recover 組合使用

典型場景

  • 防止 panic 導致程序崩潰(如 HTTP 服務器、數據庫操作等)。
  • 資源清理(如關閉文件、解鎖等),即使發生 panic 也要確保資源釋放。

示例:防止 panic 崩潰

package mainimport "fmt"func safeDivide(a, b int) (result int) {defer func() {if r := recover(); r != nil {  // 捕獲 panicfmt.Println("捕獲到 panic:", r)result = 0  // 返回默認值}}()return a / b  // 如果 b=0,會 panic
}func main() {fmt.Println(safeDivide(10, 2))  // 正常情況fmt.Println(safeDivide(10, 0))  // 除零 panic
}

輸出:

5
捕獲到 panic: runtime error: integer divide by zero
0

說明:

  • safeDivide 函數在 defer 中使用 recover 捕獲 panic。
  • 如果 b=0 導致 panic,recover 會捕獲它,并返回 0 而不是讓程序崩潰。

示例:文件操作(確保文件關閉)

package mainimport ("fmt""os"
)func readFile(filename string) {file, err := os.Open(filename)if err != nil {fmt.Println("打開文件失敗:", err)return}defer file.Close()  // 確保文件關閉,即使發生 panic// 模擬 panicpanic("讀取文件時發生錯誤!")// 正常情況下讀取文件內容// buf := make([]byte, 1024)// file.Read(buf)// fmt.Println(string(buf))
}func main() {readFile("example.txt")fmt.Println("程序繼續執行...")
}

輸出:

打開文件失敗: open example.txt: no such file or directory
程序繼續執行...

說明:

  • 即使 panic 發生,defer file.Close() 仍然會執行,確保文件被關閉。
  • 程序不會崩潰,而是繼續執行 fmt.Println("程序繼續執行...")

4. 總結

關鍵字

作用

特點

defer

延遲執行函數調用

后進先出(LIFO),即使 panic 也會執行

recover

捕獲 panic

只能在 defer

中使用,防止程序崩潰

defer + recover

錯誤恢復

確保資源釋放,防止 panic 導致程序崩潰

最佳實踐

  1. 資源清理(如文件、數據庫連接、鎖)→ defer
  2. 防止 panic 崩潰(如 HTTP 服務器、關鍵計算)→ defer + recover
  3. 避免濫用 recoverrecover 應該只用于預期內的 panic,而不是掩蓋所有錯誤(如應該用 error 返回值處理的錯誤)。

這樣,你就可以在 Go 中優雅地處理錯誤和資源管理了! 🚀

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/diannao/93097.shtml
繁體地址,請注明出處:http://hk.pswp.cn/diannao/93097.shtml
英文地址,請注明出處:http://en.pswp.cn/diannao/93097.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

Spring Boot 配置文件常用配置屬性詳解(application.properties / application.yml)

前言 Spring Boot 的一大優勢就是通過簡單的配置文件即可快速定制應用行為,而無需編寫大量 XML 配置或 Java 代碼。Spring Boot 使用 application.properties 或 application.yml 作為核心配置文件,支持豐富的配置屬性。 本文將詳細介紹 Spring Boot 常用…

uni-appDay02

1.首頁-通用輪播組件 輪播圖組件需要再首頁和分類頁使用&#xff0c;封裝成通用組件 準備組件自動導入組件 <script setup lang"ts"> import XtxSwiper from /components/XtxSwiper.vue import CustomNavbar from ./components/CustomNavbar.vue </scrip…

FastAPI入門:請求體、查詢參數和字符串校驗、路徑參數和數值校驗

請求體 FastAPI 使用請求體從客戶端&#xff08;例如瀏覽器&#xff09;向 API 發送數據。請求體是客戶端發送給 API 的數據。響應體是 API 發送給客戶端的數據。 使用 Pydantic 模型聲明請求體&#xff0c;能充分利用它的功能和優點 from fastapi import FastAPI from pydanti…

Docker的docker-compose類比Spring的ApplicationContext

總一句話是&#xff1a;Docker Compose&#xff1a;集中化管理多個容器及其依賴的資源環境&#xff1b;ApplicationContext&#xff1a;集中化管理 多個Bean 及其運行所需的資源和依賴關系。 1. 整體概念 Docker Compose&#xff1a;用于定義和運行多容器 Docker 應用程序&…

Reason-before-Retrieve(CVPR 2025)

研究方向&#xff1a;Image Captioning論文全名&#xff1a;《Reason-before-Retrieve: One-Stage Reflective Chain-of-Thoughts for Training-Free Zero-Shot Composed Image Retrieval》1. 論文介紹組合圖像檢索&#xff08;CIR&#xff09;旨在檢索與參考圖像密切相似的目標…

Idefics2:構建視覺-語言模型時,什么是重要的

溫馨提示&#xff1a; 本篇文章已同步至"AI專題精講" Idefics2&#xff1a;構建視覺-語言模型時&#xff0c;什么是重要的 摘要 隨著large language models和vision transformers的進步&#xff0c;視覺-語言模型&#xff08;VLMs&#xff09;受到了越來越多的關注…

再談fpga開發(fpga調試方法)

【 聲明&#xff1a;版權所有&#xff0c;歡迎轉載&#xff0c;請勿用于商業用途。 聯系信箱&#xff1a;feixiaoxing 163.com】我們之前在學校學習c、c的時候&#xff0c;其實學校漏掉了很重要的一個教學環節&#xff0c;那就是調試、測試。很多時候我們代碼寫出來了&#xff…

C語言中的數據結構--棧和隊列(1)

前言本屆開始我們將對數據結構中棧的內容進行講解,那么廢話不多說,我們正式進入今天的學習棧棧是一種很特殊的線性表&#xff0c;它只能在固定的一端進行插入和刪除操作&#xff0c;進行數據的插入和刪除的一端叫做棧頂&#xff0c;另外一端叫做棧底&#xff0c;棧中的元素遵守…

字符串是數據結構還是數據類型?

比較糾結的一個問題&#xff0c;以下是在網上查到后總結的&#xff0c;不知道對不對&#xff0c;歡迎討論。這是個觸及計算機科學核心概念的精妙問題&#xff01;字符串既可以被視為一種數據類型&#xff0c;也可以被視為一種數據結構&#xff0c;這取決于你觀察的視角和討論的…

Cline與Cursor深度實戰指南:AI編程助手的革命性應用

引言 在AI編程工具快速發展的今天&#xff0c;Cline和Cursor作為兩款備受矚目的AI編程助手&#xff0c;正在重新定義開發者的工作方式。作為一名深度使用這兩款工具的開發者&#xff0c;我在過去一年的實踐中積累了豐富的經驗和獨到的見解。本文將從技術角度深入分析Cline和Cur…

根本是什么

根本是什么 根本沒有了&#xff0c;枝葉還在么&#xff1f; 沒有了內涵&#xff0c;外延還有么&#xff1f; 丟棄了根本&#xff0c;再嗨也是無意義&#xff0c;無根據空虛之樂罷了。 人之所行所言所思所想所念皆欲念、歷程感懷&#xff0c;情思。所謂得失過往&#xff0c;時空…

springboot基于Java的人力資源管理系統設計與實現

管理員&#xff1a;登錄&#xff0c;個人中心&#xff0c;部門管理&#xff0c;員工管理&#xff0c;培訓信息管理&#xff0c;員工獎勵管理&#xff0c;員工懲罰管理員工考核管理&#xff0c;調薪信息管理&#xff0c;員工調動管理&#xff0c;員工工資管理員工&#xff1a;注…

金字塔降低采樣

文章目錄image_scale.hppimage_scale.cppmainimage_scale.hpp #ifndef IMAGE_SCALE_HPP #define IMAGE_SCALE_HPP#include <vector> #include <cstdint> #include <utility> // for std::pair #include <algorithm> #include <string> enum cl…

Filament引擎(四)——光照渲染Froxelizer實現分析

Froxelizer主要是用于filament光照效果的實現&#xff0c;生成光照渲染時所需的必要信息&#xff0c;幫助渲染過程中明確哪些區域受哪些光源所影響&#xff0c;是Filament中保證光照效果渲染效率的核心所在。這部分的源碼&#xff0c;可以結合filament官方文檔中Light Path部分…

2025 環法對決,VELO Angel Glide 坐墊輕裝上陣

2025環法第16賽段的風禿山之巔&#xff0c;當最后一縷夕陽沉入云層&#xff0c;山風裹挾著礫石的氣息掠過賽道&#xff0c;一場足以載入史冊的激戰正酣。帕雷-潘特的肌肉在汗水里賁張&#xff0c;鏈條與齒輪的咬合聲混著粗重喘息&#xff0c;在171.5公里賽程的最后3公里陡坡上&…

Linux程序->進度條

進度條最終效果&#xff1a; 目錄 進度條最終效果&#xff1a; 一&#xff1a;兩個須知 1&#xff1a;緩沖區 ①&#xff1a;C語言自帶緩沖區 ②&#xff1a;緩沖區的刷新策略 2&#xff1a;回車和換行的區別 二&#xff1a;倒計時程序 三&#xff1a;入門板進度條的實…

Python爬蟲實戰:研究tldextract庫相關技術構建新聞網站域名分析爬蟲系統

1. 引言 網絡爬蟲作為一種自動獲取互聯網信息的技術,在數據挖掘、信息檢索、輿情分析等領域有著廣泛的應用。Python 因其豐富的庫和簡潔的語法,成為了開發爬蟲的首選語言。tldextract 是 Python 中一個強大的域名解析庫,能夠準確地從 URL 中提取頂級域名、二級域名等關鍵信…

【算法-華為機試-火星基地改造】

基地改造題目描述目標輸入輸出代碼實現題目描述 在2XXX年&#xff0c;人們發現了一塊火星地區&#xff0c;這里看起來很適合建設新家園。但問題是&#xff0c;我們不能一次性將這片地區的空氣變得適合人類居住&#xff0c;得分步驟來。 把這片火星地區想象成一個巨大的棋盤。棋…

C++入門自學Day1-- C語言的宏函數和C++內聯函數

一、函數調用開銷函數調用會涉及&#xff1a;參數壓棧&#xff08;或寄存器傳參&#xff09;跳轉到函數體返回值處理棧幀銷毀這個過程對小函數來說可能非常浪費&#xff0c;因此&#xff0c;宏函數和內聯函數的目的就是避免“函數調用的開銷”&#xff0c;通過代碼展開&#xf…

Pytorch混合精度訓練最佳實踐

混合精度訓練&#xff08;Mixed Precision Training&#xff09;是一種通過結合單精度&#xff08;FP32&#xff09;和半精度&#xff08;FP16/FP8&#xff09;計算來加速訓練、減少顯存占用的技術。它在保持模型精度的同時&#xff0c;通常能帶來 2-3 倍的訓練速度提升&#x…