Go高级特性探究之recover捕获panic详解

 更新时间:2023年06月06日 11:01:41   作者:tracy小猫  
在Go语言中,当程序出现panic(即运行时错误)时,程序会立即停止当前的执行流程,而recover函数的作用就是捕获这个panic,下面就来看看具体是怎么操作的吧

在Go语言中,当程序出现panic(即运行时错误)时,程序会立即停止当前的执行流程,并在函数调用堆栈向上逐层返回,直到遇到recover函数或程序终止为止。

而recover函数的作用就是捕获这个panic,并恢复正常的执行流程。在Gin框架中,提供了recover中间件来自动捕获panic,并转换为HTTP 500错误返回给客户端。

使用

使用recover中间件非常简单,只需要在Gin路由中添加即可:

router := gin.Default()
router.Use(gin.Recovery())

需要注意的是,recover中间件应该在Gin路由中的第一个声明,以确保可以捕获所有的panic。

配合日志打印与埋点上报

在API开发中,当用户请求接口时,有时候会遇到一些问题,如访问url错误、参数错误、数据库连接超时等。虽然recover中间件可以避免由程序错误导致的panic,但仍然需要记录这些错误信息来协助问题的排查和定位。

因此,我们可以配合日志打印和埋点上报来记录这些错误。以日志打印为例,Gin框架提供了官方的Logger中间件,可以使用Logger来记录错误信息:

router := gin.Default()
// Logger 中间件将请求的URL、响应时间、响应状态码和请求的IP地址写入日志文件
router.Use(gin.Logger())
// Recover 中间件将 panic 转换为 500 错误,并写入日志文件
router.Use(gin.Recovery())
// 业务代码
router.GET("/api", func(c \*gin.Context) {
    // code
    if err != nil {
        // 某个函数抛出了 panic
        log.Printf("\[ERROR] - %v\n", err)
        c.AbortWithStatusJSON(http.StatusInternalServerError, gin.H{
            "message": "内部错误,请稍后重试",
        })
        return
    }
    // code
})

在上述代码中,我们使用log来记录错误信息,并在响应中返回了错误提示。这样我们就能及时的发现问题并进行排查了。

当然,我们还可以在记录错误信息的同时上传到埋点工具中,例如Sentry、Zipkin等,来实现自动的错误上报和监控。

recover在开源项目中的使用

recover中间件在开源项目中广泛应用,例如Prometheus、etcd、Kubernetes等项目中都有使用。

以etcd为例,它使用recover中间件捕获所有的panic,并在日志中记录错误信息,如下所示:

func (s *EtcdServer) recoverAndLog(rctx rpctypes.Context, w http.ResponseWriter, req *http.Request) {
    data, err := ioutil.ReadAll(req.Body)
    if err != nil {
        writeError(w, rctx, err)
        return
    }
    defer func() {
        if v := recover(); v != nil {
            log.Printf("panic: %v", v)
            writeError(w, rctx, fmt.Errorf("panic: %v", v))
        }
    }()
    // code
}

在该函数中,使用了defer关键字调用recover函数捕获panic,并使用log记录错误信息并返回错误提示。

总结

通过Gin框架中的recover中间件,我们可以方便的捕获和处理程序运行时的错误,从而提高了API服务的稳定性和可靠性。同时,配合日志打印和埋点上报,可以更好地记录错误信息和辅助问题的排查和解决。在开源项目中,recover中间件也被广泛应用,并帮助了很多项目实现了稳定的运行。

到此这篇关于Go高级特性探究之recover捕获panic详解的文章就介绍到这了,更多相关Go recover捕获panic内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • Golang使用Channel组建高并发HTTP服务器

    Golang使用Channel组建高并发HTTP服务器

    Golang 作为一门高效的语言,在网络编程方面表现也非常出色,这篇文章主要介绍了如何使用 Golang 和 Channel 组建高并发 HTTP 服务器,感兴趣的可以了解一下
    2023-06-06
  • Golang使用Swagger文档教程详解

    Golang使用Swagger文档教程详解

    这篇文章主要为大家详细介绍Golang使用Swagger文档教程的相关知识,文中通过示例代码讲解详细,具有一定的借鉴价值,感兴趣的小伙伴可以学习一下
    2023-12-12
  • Golang errgroup 设计及实现原理解析

    Golang errgroup 设计及实现原理解析

    这篇文章主要为大家介绍了Golang errgroup 设计及实现原理解析,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2022-08-08
  • GO接收GET/POST参数及发送GET/POST请求的实例详解

    GO接收GET/POST参数及发送GET/POST请求的实例详解

    这篇文章主要介绍了GO接收GET/POST参数及发送GET/POST请求,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2020-12-12
  • Golang Gorm 更新字段save、update、updates

    Golang Gorm 更新字段save、update、updates

    在gorm中,批量更新操作可以通过使用Update方法来实现,本文主要介绍了Golang Gorm 更新字段save、update、updates,具有一定的参考价值,感兴趣的可以了解一下
    2023-12-12
  • golang interface判断为空nil的实现代码

    golang interface判断为空nil的实现代码

    这篇文章主要介绍了golang interface判断为空nil的实现代码,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2021-04-04
  • Golang时间及时间戳的获取转换超全面详细讲解

    Golang时间及时间戳的获取转换超全面详细讲解

    说实话,golang的时间转化还是很麻烦的,最起码比php麻烦很多,下面这篇文章主要给大家介绍了关于golang时间/时间戳的获取与转换的相关资料,文中通过实例代码介绍的非常详细,需要的朋友可以参考下
    2022-12-12
  • 详解Golang如何实现支持随机删除元素的堆

    详解Golang如何实现支持随机删除元素的堆

    堆是一种非常常用的数据结构,它能够支持在O(1)的时间复杂度获取到最大值(或最小值)。本文主要介绍了如何实现支持O(log(n))随机删除元素的堆,需要的可以参考一下
    2022-09-09
  • Go打包附件内容到执行文件的方法

    Go打包附件内容到执行文件的方法

    处于种种原因, 我们不希望这部分额外的内容以附件的形式出现, 有没有什么办法能够将附件内容直接打包进可执行文件中呢,下面小编给大家介绍下Go打包附件内容到执行文件的方法,感兴趣的朋友一起看看吧
    2023-03-03
  • Go和RabbitMQ构建高效的消息队列系统

    Go和RabbitMQ构建高效的消息队列系统

    本文主要介绍了使用Go语言和RabbitMQ搭建一个简单的消息队列系统,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2025-01-01

最新评论