当前位置: 首页 > news >正文

Go 语言的 panic 和 recover

Go 语言的 panic 和 recover 是两种用于处理异常的机制。

它们允许在程序运行过程中进行错误处理,特别是处理那些不可恢复的错误和恢复程序的执行。

panic 和 recover 并不像其他语言中的 try-catch 机制那样常见,而是提供了控制程序流程的一种方法。

  1. panic 机制

panic 用于表示程序遇到了一个不可恢复的错误,或者程序处于一个不应继续执行的状态。它会触发运行时的异常,并停止当前函数的执行,直到调用 recover 或程序退出。

1.1 panic 的使用

当你遇到一个严重的错误或不合法的操作时,可以调用 panic 来终止当前函数的执行,并开始触发一系列的 defer 函数。

panic 会导致当前函数的执行停止,并且会递归地向上层函数传播,直到程序结束或者有 recover 恢复它。

使用 panic 终止程序


func divide(a, b int) int {if b == 0 {panic("division by zero") // 如果除数为零,抛出 panic}return a / b
}func main() {fmt.Println("Starting program")// 这里会触发 panicresult := divide(10, 0)fmt.Println("Result:", result) // 这行代码不会执行
}
当 b == 0 时,panic 被触发,程序会停止当前函数的执行,并开始递归传播。panic 的错误信息是 "division by zero",这将显示在控制台。调用 panic 后,程序停止执行,任何后续代码都不会被执行,除非在调用链中有 recover
  1. recover 机制

recover 是 Go 语言中用来从 panic 中恢复的函数。它只能在 defer 中使用。当 recover 被调用时,它会捕获到正在执行的 panic,并停止 panic 继续传播,恢复程序的执行。

2.1 recover 的使用

recover 会返回 panic 时传递的值,并恢复程序的正常执行。

如果 recover 没有在 panic 发生时被调用,panic 会继续向上传播,直到程序退出。

只有在 defer 函数内部,recover 才能捕获到 panic。

使用 recover 恢复程序


func divide(a, b int) int {if b == 0 {panic("division by zero") // 如果除数为零,抛出 panic}return a / b
}func safeDivide(a, b int) (result int, err string) {defer func() {if r := recover(); r != nil {err = fmt.Sprintf("Recovered from panic: %v", r)}}()result = divide(a, b) // 可能会触发 panicreturn
}func main() {result, err := safeDivide(10, 0)if err != "" {fmt.Println("Error:", err)} else {fmt.Println("Result:", result)}
}
Error: Recovered from panic: division by zero
safeDivide 函数尝试执行 divide,如果 divide 触发了 panicrecover 会捕获到并停止 panic 继续传播。defer 中的匿名函数通过 recover() 捕获 panic,并将 panic 的信息作为错误返回。程序恢复执行并返回错误信息,而不会崩溃。
  1. panic 和 recover 的工作流程

panic 的传播:

当 panic 被触发时,Go 会立即停止当前函数的执行,并开始递归地向上传播 panic。

每次 panic 传播时,都会执行当前函数的所有 defer 语句。

recover 捕获 panic:

如果在某个 defer 语句中调用 recover,它将会捕获当前的 panic 并停止 panic 的传播。

recover 返回 panic 时传递的参数,通常是一个错误信息。

如果没有 recover 捕获,panic 将继续传播,直到程序退出。

  1. panic 和 recover 使用的注意事项

不要滥用 panic 和 recover:Go 语言的设计原则鼓励使用显式的错误处理机制(例如返回错误值),而不是通过 panic 来表示常规错误。panic 应该只用于处理那些程序无法恢复的错误(例如数组越界、无法恢复的逻辑错误等)。

defer 和 recover:recover 必须在 defer 函数中调用才能有效。如果 recover 不在 defer 中,它将无法捕获到 panic。

panic 和 recover 用于同步代码:panic 和 recover 通常用于同步函数的错误处理。它们不能用于并发的错误处理(例如 goroutine 中的错误处理)。对于并发程序,Go 更倾向于通过返回错误值来处理错误。

panic 和 recover 的机制引入了较高的开销,通常应避免在高频调用的代码中使用 panic。它们更适合处理那些异常、不可恢复的错误,而不是正常的程序流程控制。

  1. 实际应用中的使用场景

panic 的场景:当程序遇到无法继续执行的严重错误时,调用 panic。例如:空指针解引用、数组越界等。

recover 的场景:当你希望在程序中捕获并恢复某些不可预见的错误时,使用 recover。常见的场景包括:Web 服务器的中间件处理、数据库事务的回滚等。

Web 服务器的 panic 恢复

func handler(w http.ResponseWriter, r *http.Request) {defer func() {if r := recover(); r != nil {fmt.Println("Recovered from panic:", r)http.Error(w, "Internal server error", http.StatusInternalServerError)}}()panic("Something went wrong") // 模拟一个 panic
}func main() {http.HandleFunc("/", handler)fmt.Println("Starting server at :8080...")if err := http.ListenAndServe(":8080", nil); err != nil {fmt.Println("Server failed:", err)}
}服务器启动:当你运行程序时,main 函数启动 HTTP 服务器并监听端口 8080。触发 panic:当你访问根路径(http://localhost:8080/)时,handler 函数会被触发。在 handler 函数中,程序会故意执行 panic("Something went wrong"),模拟一个错误的发生。recover 捕获 panicpanic 触发后,程序会立即停止当前函数的执行。此时,defer 语句中的匿名函数被调用,recover 会捕获到 panic,然后通过 http.Error 返回 500 错误响应给客户端。恢复并继续执行:由于 recover 捕获并处理了 panic,程序不会崩溃,而是继续执行。
http://www.dtcms.com/a/441819.html

相关文章:

  • Spring Cloud Netflix Eureka:从微服务基础到高可用集群实战
  • 网站建设 人天价格游戏制作软件免费下载
  • CSP-S2025复赛模拟4补题报告(无AC code)
  • 什么是Agent及其在人工智能中的角色
  • 爱授权系统V3.0免授权版 支持插件和插件商城
  • MySQL 本机压测分析
  • 华清远见25072班C++学习假期10.4作业
  • 建网站学什么软件全国医院的网站建设
  • 【深度学习计算机视觉】09:语义分割和数据集——应用场景与前沿探索
  • 【LeetCode热题100】No.1——两数之和(Java)
  • 系分论文《论边缘计算在工业质检系统中的分析与设计》
  • 利用 ArcMap 的 MXD 布局视图以及ArcPy 脚本实现批量自动生成油井点之记并导出 PDF(实操+亲测)
  • 计算机工作原理(简单介绍)
  • 自己如何建设网站聊天室做医药代表去什么招聘网站
  • 指针和数组解析
  • 【AI4S】3DSMILES-GPT:基于词元化语言模型的3D分子生成
  • Transformer推理优化全景:从模型架构到硬件底层的深度解析
  • MySQL 索引全解析:结构、优化与索引下推实战指南​
  • clear configuration interface概念及题目
  • 设计模式(C++)详解——策略模式(1)
  • 基于html5设计的网站建设做一些购物网站
  • Vivado综合通关指南:从IP打包失败到工具崩溃的四重考验
  • 语义分割概述
  • 数据结构之排序算法
  • 绍兴网站建设优化手机企业网站建设开发
  • 偏导数解释
  • Linux内核与设备管理:USB存储驱动usb_storage/uas的安全卸载与复原
  • fallocate: fallocate failed: Text file busy
  • visio实现扇形图绘制的方式方法-以三等分扇形为例
  • 以太坊私有链搭建与智能合约部署指南