【Go】 探索 Go 语言的内建函数 recover


山水间歌声回荡

回荡思念的滚烫

去年的家书两行

读来又热了眼眶

云水边静沐暖阳

烟波里久违的故乡

别来无恙

你在心上

🎵 张靓颖/张杰《燕归巢》


在 Go 语言中,recover 是一个内建函数,用于从 panic 状态中恢复执行。recover 只能在延迟函数(defer)中使用,如果没有 panic 被触发,recover 返回 nil。本文将详细介绍 recover 函数的使用场景和示例。

recover 函数的基本语法

recover 函数的基本语法如下:

go 复制代码
recover() interface{}

使用 recover 恢复 panic

recover 函数通常与 defer 和 panic 一起使用,以防止程序崩溃并提供恢复机制。

基本示例

go 复制代码
package main

import "fmt"

func main() {
    defer func() {
        if r := recover(); r != nil {
            fmt.Println("捕获到恐慌:", r)
        }
    }()
    
    fmt.Println("程序开始")
    panic("发生了不可恢复的错误")
    fmt.Println("程序结束") // 不会执行
}

在这个例子中,当 panic 触发时,recover 函数捕获恐慌信息,使得程序不会崩溃,并打印 "捕获到恐慌: 发生了不可恢复的错误"。

实际应用中的 recover 使用场景

防止程序崩溃

在一些关键的地方使用 recover 可以防止整个程序崩溃,特别是在服务器程序中。

go 复制代码
package main

import "fmt"

func main() {
    safeFunction()
    fmt.Println("程序继续执行")
}

func safeFunction() {
    defer func() {
        if r := recover(); r != nil {
            fmt.Println("捕获到恐慌:", r)
        }
    }()
    
    panic("一些错误")
    fmt.Println("不会执行到这里")
}
多个 defer 的 recover 使用

多个 defer 的场景中,只有最先被推入栈的 defer 可以捕获 panic。

go 复制代码
package main

import "fmt"

func main() {
    defer func() {
        if r := recover(); r != nil {
            fmt.Println("第一个 defer 捕获到恐慌:", r)
        }
    }()
    
    defer func() {
        if r := recover(); r != nil {
            fmt.Println("第二个 defer 捕获到恐慌:", r)
        }
    }()
    
    panic("触发恐慌")
}

在这个例子中,第二个 defer 中的 recover 无法捕获 panic,因为 panic 被第一个 defer 捕获并处理。

使用 recover 的注意事项

  • 只能在 defer 中使用:recover 必须在延迟函数中使用,否则无法捕获到 panic。
  • 理解 panic 和 recover 的关系:panic 会停止当前函数的执行并开始逐层向上清理调用栈,直到遇到 defer 中的 recover。
  • 适度使用:panic 和 recover 应该用于处理不可恢复的错误,不应滥用来控制正常的程序流程。

示例代码

以下是一个综合示例,展示了如何在不同情况下使用 recover 函数:

go 复制代码
package main

import "fmt"

func main() {
    // 示例 1: 基本使用
    defer func() {
        if r := recover(); r != nil {
            fmt.Println("捕获到恐慌:", r)
        }
    }()
    
    fmt.Println("程序开始")
    panic("发生了不可恢复的错误")
    fmt.Println("程序结束") // 不会执行

    // 示例 2: 防止程序崩溃
    safeFunction()
    fmt.Println("程序继续执行")

    // 示例 3: 多个 defer
    defer func() {
        if r := recover(); r != nil {
            fmt.Println("第一个 defer 捕获到恐慌:", r)
        }
    }()
    
    defer func() {
        if r := recover(); r != nil {
            fmt.Println("第二个 defer 捕获到恐慌:", r)
        }
    }()
    
    panic("触发恐慌")
}

func safeFunction() {
    defer func() {
        if r := recover(); r != nil {
            fmt.Println("捕获到恐慌:", r)
        }
    }()
    
    panic("一些错误")
    fmt.Println("不会执行到这里")
}

总结

recover 是 Go 语言中的一个强大工具,用于从 panic 状态中恢复执行。理解和正确使用 recover 函数,可以显著提高代码的健壮性和容错能力。希望这篇博客能帮助你更好地理解和使用 Go 语言中的 recover 函数,让你的编程之旅更加顺畅。

相关推荐
舒一笑5 分钟前
Started TttttApplication in 0.257 seconds (没有 Web 依赖导致 JVM 正常退出)
jvm·spring boot·后端
张柏慈5 分钟前
JavaScript性能优化30招
开发语言·javascript·性能优化
M1A126 分钟前
Java Enum 类:优雅的常量定义与管理方式(深度解析)
后端
promising-w33 分钟前
【嵌入式C语言】六
c语言·开发语言
打不了嗝 ᥬ᭄1 小时前
Linux 信号
linux·开发语言·c++·算法
AAA修煤气灶刘哥1 小时前
别再懵了!Spring、Spring Boot、Spring MVC 的区别,一篇讲透
后端·面试
ZLRRLZ1 小时前
【C++】C++11
开发语言·c++
全栈软件开发1 小时前
PHP域名授权系统网站源码_授权管理工单系统_精美UI_附教程
开发语言·ui·php·php域名授权·授权系统网站源码
柏油1 小时前
MySQL 字符集 utf8 与 utf8mb4
数据库·后端·mysql
誰能久伴不乏1 小时前
Qt 动态属性(Dynamic Property)详解
开发语言·qt