Golang 中比较常见的 panic 异常原因之一

目录

  • 前言
  • 正文
  • 结尾

前言

在 Golang 中,当异常发生时不管是主动触发 panic 还是由于编码错误导致的 panic,我们都可以使用 recover 进行捕获。当时前提必须定义 defer 语句,且 defer 必须放在 panic 之前定义,另外 recover 只有在 defer 调用的函数中才有效。

正文

今天本文介绍一个编码不规范导致的 panic 异常,下面是错误日志,从日志中我们可以看到程序发生了 panic 异常,并且这个 panic 已经 Gin 框架自带的 Recovery 中间件捕获到了。

报错信息详情:

2021/11/22 09:22:47 [Recovery] 2021/11/22 - 09:22:47 panic recovered:
POST /api/transcode/start HTTP/1.1
Host: lozen.test.cn:9903
Connection: close
Accept-Encoding: gzip
Connection: close
Content-Length: 441
Content-Type: application/json
User-Agent: GoFrameHTTPClient v1.15.4
interface conversion: interface {} is nil, not map[string]interface {}
/usr/local/go/src/runtime/iface.go:261 (0x40ce8e)
/root/work/bag/src/server/controllers/transcode.go:626 (0xfdf3a4)
/root/go/pkg/mod/github.com/gin-gonic/gin@v1.7.3/context.go:165 (0xfa5deb)
/root/go/pkg/mod/git.baijiashilian.com/!l!l!l/gloud/gobase@v0.0.0-20211109104743-9df882862f80/utils/trace_middleware.go:18 (0xfa5dca)
/root/go/pkg/mod/github.com/gin-gonic/gin@v1.7.3/context.go:165 (0xfe79f5)
/root/work/bag/src/server/middleware/logger.go:15 (0xfe79b4)
/root/go/pkg/mod/github.com/gin-gonic/gin@v1.7.3/context.go:165 (0xf55499)
/root/go/pkg/mod/github.com/gin-gonic/gin@v1.7.3/recovery.go:99 (0xf55480)
/root/go/pkg/mod/github.com/gin-gonic/gin@v1.7.3/context.go:165 (0xf54573)
/root/go/pkg/mod/github.com/gin-gonic/gin@v1.7.3/logger.go:241 (0xf54532)
/root/go/pkg/mod/github.com/gin-gonic/gin@v1.7.3/context.go:165 (0xf4a909)
/root/go/pkg/mod/github.com/gin-gonic/gin@v1.7.3/gin.go:489 (0xf4a8ef)
/root/go/pkg/mod/github.com/gin-gonic/gin@v1.7.3/gin.go:445 (0xf4a3db)
/usr/local/go/src/net/http/server.go:2887 (0x725d42)
/usr/local/go/src/net/http/server.go:1952 (0x72116c)
/usr/local/go/src/runtime/asm_amd64.s:1371 (0x473fc0)

日志的下半段是报错的具体原因,总结下来就是:

interface conversion: interface {} is nil, not map[string]interface {}

根本原因是在服务器端解析参数时,没有对 video 字段进行校验,当 video 字段为空时就会发生上述错误。因为设计之初,云转码服务仅支持视频转码,后来支持了单音频编码功能,比如 mp3、aac。业务端调用原来接口的时候就去掉了 video 字段,如下图所示:

Golang 中比较常见的 panic 异常原因之一

避免上述错误有两种方式,第一种方法,也是最根本的方法,即修改云转码服务代码,不再认为 video 字段是必传项,对 video 字段进行校验。

第二种方法是业务端调用云转码接口传参数时,video 字段可以传空结构体,如下图所示:

Golang 中比较常见的 panic 异常原因之一

注意:空结构体的形式是大括号 {},不是 "",也不是 nil

结尾

最后,总结一下 Golang 在处理异常捕获时的一些注意事项,首先,defer 语句需要提前定义,否则当 panic 发生时,recover 是无法捕获到 panic 异常的。其次,recover 处理异常后,逻辑并不会恢复到 panic 的实际发生位置,而是执行 defer 之后的语句段。最后,多个 defer 语句会形成 defer 栈,后定义的 defer 语句会先执行。


作者简介:大家好,我是 liuzhen007,是一位音视频技术爱好者,同时也是CSDN博客专家、华为云享专家、InfoQ 签约作者,欢迎关注我分享更多干货!


上一篇:如何恢复部分WannaCry勒索软件加密文件


下一篇:LINUX使用sed,字串中包含特殊字符怎么办?