在 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…