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

「这是我参与11月更文挑战的第26天,活动详情查看:2021最后一次更文挑战

目录

  • 前言
  • 正文
  • 结尾

前言

在 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/[email protected]/context.go:165 (0xfa5deb)

/root/go/pkg/mod/git.baijiashilian.com/!l!l!l/gloud/[email protected]/utils/trace_middleware.go:18 (0xfa5dca)

/root/go/pkg/mod/github.com/gin-gonic/[email protected]/context.go:165 (0xfe79f5)

/root/work/bag/src/server/middleware/logger.go:15 (0xfe79b4)

/root/go/pkg/mod/github.com/gin-gonic/[email protected]/context.go:165 (0xf55499)

/root/go/pkg/mod/github.com/gin-gonic/[email protected]/recovery.go:99 (0xf55480)

/root/go/pkg/mod/github.com/gin-gonic/[email protected]/context.go:165 (0xf54573)

/root/go/pkg/mod/github.com/gin-gonic/[email protected]/logger.go:241 (0xf54532)

/root/go/pkg/mod/github.com/gin-gonic/[email protected]/context.go:165 (0xf4a909)

/root/go/pkg/mod/github.com/gin-gonic/[email protected]/gin.go:489 (0xf4a8ef)

/root/go/pkg/mod/github.com/gin-gonic/[email protected]/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 字段,如下图所示:

image.png

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

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

image.png

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

结尾

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

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

猜你喜欢

转载自juejin.im/post/7035147962695024677