深入理解Go语言中defer和panic的执行顺序

 更新时间:2025年05月26日 09:32:25   作者:纸鸢666  
defer 和 panic 的执行顺序是一个重要的概念,本文主要介绍了Go语言中defer和panic的执行顺序,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧

简介

在 Go 语言中,defer 和 panic 的执行顺序是一个重要的概念。本文将通过一个示例代码来详细解释为什么 defer 中的代码会先执行,而 panic 的错误信息稍后才输出。

示例代码

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()")
}

执行顺序解释

1. defer 的执行机制

defer 的作用是延迟执行一个函数调用,直到包含它的函数执行完毕。无论函数是正常结束还是因为错误(如 panic)结束,所有被 defer 延迟的函数都会按照后进先出(LIFO)的顺序执行。

2. panic 的传播机制

当 panic 被触发时,Go 会立即中断当前函数的正常执行流程,并开始向上层调用栈传播错误信号。在这个过程中,Go 会依次执行当前函数中所有被 defer 延迟的函数。这些延迟函数可以通过 recover() 捕获并处理 panic。

3. 代码执行顺序

(1) 执行 main() 函数

func main() {
    defer func() {
        if r := recover(); r != nil {
            fmt.Println("Recovered. Error:\n", r)
        }
    }()

    mayPanic()  // 触发 panic
    fmt.Println("After mayPanic()")  // 这行代码不会执行
}

(2) 调用 mayPanic()

func mayPanic() {
    panic("a problem")
}

panic("a problem") 被触发,程序会立即中断当前函数的执行,并将 panic 信息传播到上层调用栈。

(3) 触发 defer 延迟函数

由于 panic 的触发,Go 会开始执行 main() 函数中被 defer 延迟的函数:

defer func() {
    if r := recover(); r != nil {
        fmt.Println("Recovered. Error:\n", r)
    }
}()

在这个延迟函数中,recover() 被调用,捕获了 panic 的错误信息 "a problem",并打印出来。

(4) panic 被恢复

由于 recover() 成功捕获了 panic,程序的正常执行流程得以恢复。不过,panic 的传播已经中断了 main() 函数的正常执行,因此 fmt.Println("After mayPanic()") 不会执行。

4. 输出结果顺序

按照以上执行顺序,程序的输出如下:

Recovered. Error:
 a problem

为什么 defer 先执行?

这是因为 panic 的传播机制会触发所有 defer 延迟函数的执行。defer 的设计初衷是确保某些重要的清理操作(如释放资源、关闭文件等)能够在函数结束时执行,即使函数是因 panic 而异常结束的。

总结来说:

  • panic 会中断当前函数的执行。

  • Go 会依次执行所有被 defer 延迟的函数。

  • recover() 可以在延迟函数中捕获 panic 并恢复程序的执行。

总结

通过上述代码和解释,我们可以清楚地看到 defer 和 panic 的执行顺序是由 Go 语言的设计规则决定的。defer 确保了清理操作的执行,而 panic 的传播机制允许我们在延迟函数中捕获并处理错误。

到此这篇关于Go语言中defer和panic的执行顺序的文章就介绍到这了,更多相关Go语言 defer和panic执行顺序内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • Golang中下划线(_)的不错用法分享

    Golang中下划线(_)的不错用法分享

    golang中的下划线表示忽略变量的意思,也没有产生新的变量,但是后面的表达式依然会被执行,本文为大家整理了golang中下划线的一些不错的用法,需要的可以参考下
    2023-05-05
  • 一文深入解析Go语言中net/url包的URL处理机制

    一文深入解析Go语言中net/url包的URL处理机制

    本文介绍了Go语言中net/url包的使用和原理,通过解析URL字符串、查询参数、构建URL等示例展示了其功能,并深入剖析了Go的URL解析机制,强调了结构化数据建模的重要性,指出URL解析不仅仅是字符串操作,更是资源定位规则的标准化表达,需要的朋友可以参考下
    2026-05-05
  • Golang中实现数据脱敏处理的go-mask包分享

    Golang中实现数据脱敏处理的go-mask包分享

    这篇文章主要是来和大家分享一个在输出中对敏感数据进行脱敏的工作包:go-mask,可以将敏感信息输出的时候替换成星号或其他字符,感兴趣的小编可以跟随小编一起了解下
    2023-05-05
  • Golang实现Redis事务深入探究

    Golang实现Redis事务深入探究

    这篇文章主要介绍了Golang实现Redis事务深入探究,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2024-01-01
  • Go语言中如何进行包管理

    Go语言中如何进行包管理

    在Go语言中,包(package)是函数和数据的集合,用于组织代码,实现模块化开发,本文将结合实际案例,详细讲解Go语言包管理的用法,有需要的可以参考下
    2024-10-10
  • k8s容器互联flannel vxlan通信原理

    k8s容器互联flannel vxlan通信原理

    这篇文章主要为大家介绍了k8s容器互联flannel vxlan通信原理详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2023-04-04
  • 如何使用 Go 和 Excelize 构建电子表格

    如何使用 Go 和 Excelize 构建电子表格

    这篇文章主要介绍了如何使用Go和Excelize构建电子表格,文章围绕主题展开详细的内容介绍,具有一定的参考价值,需要的小伙伴可以参考一下
    2022-09-09
  • 浅谈Go Channel 高级实践

    浅谈Go Channel 高级实践

    这篇文章主要介绍了浅谈Go Channel 高级实践,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2018-08-08
  • Go目录文件路径操作的实现

    Go目录文件路径操作的实现

    在Go语言中,可以使用绝对路径或相对路径来表示文件路径,本文就来介绍一下Go目录文件路径操作,感兴趣的可以了解一下
    2023-10-10
  • Go语言基础go接口用法示例详解

    Go语言基础go接口用法示例详解

    这篇文章主要为大家介绍了Go语言基础关于go接口的用法示例详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,在日升职加薪
    2021-11-11

最新评论