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

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

目录

  • 前言
  • 正文
  • 结尾

前言

在 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 字段,如下图所示:

image.png

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

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

image.png

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

结尾

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


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


目录
相关文章
|
5月前
|
Go
golang环境安装异常【已解决】
golang环境安装异常【已解决】
26 2
|
3月前
|
Go
实验深度理解Go中try...catch...的panic、defer、recover用法
文章通过实验代码演示了Go语言中如何使用panic、defer和recover函数来模拟try...catch...的异常处理机制,并详细解释了每个函数的作用和在异常处理中的使用场景。
32 0
|
3月前
|
Java Serverless Go
Golang 开发函数计算问题之在 Golang 中避免 "concurrent map writes" 异常如何解决
Golang 开发函数计算问题之在 Golang 中避免 "concurrent map writes" 异常如何解决
|
5月前
|
Go Windows
golang hello 安装环境异常【已解决】
golang hello 安装环境异常【已解决】
35 1
|
6月前
|
Go 开发者
Golang深入浅出之-Go语言 defer、panic、recover:异常处理机制
Go语言中的`defer`、`panic`和`recover`提供了一套独特的异常处理方式。`defer`用于延迟函数调用,在返回前执行,常用于资源释放。它遵循后进先出原则。`panic`触发运行时错误,中断函数执行,直到遇到`recover`或程序结束。`recover`在`defer`中捕获`panic`,恢复程序执行。注意避免滥用`defer`影响性能,不应对可处理错误随意使用`panic`,且`recover`不能跨goroutine捕获panic。理解并恰当使用这些机制能提高代码健壮性和稳定性。
125 2
|
JSON Go 数据格式
Golang 语言怎么使用 panic 函数?
Golang 语言怎么使用 panic 函数?
83 0
|
6月前
|
人工智能 Go 开发者
Golang语言异常机制解析:错误策略与优雅处理
Golang语言异常机制解析:错误策略与优雅处理
|
6月前
|
Go
Go语言中的异常处理:理解panic与recover
【2月更文挑战第7天】Go语言虽然以简洁和直接错误处理机制而著称,但它也提供了`panic`和`recover`这两个内置函数来处理程序中的异常情况。本文将深入探讨Go语言中的异常处理机制,包括`panic`和`recover`的使用场景、原理以及最佳实践,帮助读者更好地理解如何在Go中处理异常情况。
|
6月前
|
存储 编译器 Go
Golang底层原理剖析之panic与recover
Golang底层原理剖析之panic与recover
61 0
|
6月前
|
网络协议 BI Go
Go-异常处理(defer recover panic)
Go-异常处理(defer recover panic)
71 0