【Gee】Day7:错误恢复

server/2025/2/24 13:53:21/
http://www.w3.org/2000/svg" style="display: none;">

Day7:错误恢复

今天的任务是:

  • 实现错误处理机制。https://i-blog.csdnimg.cn/direct/60d1933ac59c4180880533d400661ef7.jpeg#pic_center" alt="请添加图片描述" />

panic

在 Golang 中,较为常见的错误处理方式是返回 error,由调用者决定后续如何处理。但如果是无法恢复的错误,可以手动触发 panic,当然如果在程序运行时出现类似于数组越界的错误,panic 也会触发。panic 会终止当前程序的执行并退出

defer

panic 会导致程序被终止,但是在退出前,会先处理完当前协程(注意,main 函数本身也是一个协程,可以理解为它是主协程)上已经 defer 的任务,执行完后再退出。

可以 defer 多个任务,在同一个函数中 defer 多个任务时,会逆序执行,即先执行最后 defer 的任务。

defer 的任务执行完成后,panic 会继续抛出,导致程序非正常结束。

recover

Golang 提供了内置的 recover 函数,可以避免因为 panic 导致的整个程序终止,recover 只在 defer 中生效

Gee 的错误处理机制

我们在第六天实现的框架中没有加入异常处理机制,如果代码中存在会触发 panic 的 bug,程序很容易宕机。

今天我们在 gee 中添加一个非常简单的错误处理机制,即在此类型错误发生时,向用户返回 Internal Server Error,并在日志中打印必要的错误信息,方便进行错误定位。

我们之前已经实现了中间件机制,错误处理可以作为一个中间件,增强 gee 的能力。

新增 gee/recovery.go,在这个文件中实现中间件 Recovery:

// print stack trace for debug
func trace(message string) string {var pcs [32]uintptrn := runtime.Callers(3, pcs[:])var str strings.Builderstr.WriteString(message + "\nTraceback:")for _, pc := range pcs[:n] {fn := runtime.FuncForPC(pc)file, line := fn.FileLine(pc)str.WriteString(fmt.Sprintf("\n\t%s:%d", file, line))}return str.String()
}func Recovery() HandlerFunc {return func(c *Context) {defer func() {if err := recover(); err != nil {message := fmt.Sprintf("%s", err)log.Printf("%s\n\n", trace(message))c.Fail(http.StatusInternalServerError, "Internal Server Error")}}()c.Next()}
}

其中的 trace() 函数用于触发 panic 的堆栈信息。至此,Gee 的错误处理机制已经完成。

Demo

package mainimport ("gee/gee""net/http"
)func main() {r := gee.New()r.Use(gee.Logger(), gee.Recovery())	// 使用 Recovery 中间件r.GET("/", func(c *gee.Context) {c.String(http.StatusOK, "Hello Geektutu\n")})// index out of range for testing Recovery()r.GET("/panic", func(c *gee.Context) {names := []string{"geektutu"}c.String(http.StatusOK, names[100])})r.Run(":9999")
}

至此,我们完成了 Geektutu 大佬的 Gee Web 框架教程,并实现了完整的 Web 框架 Gee。简单回顾一下,Gee 使用 Context 封装了 http 的 ResponseWriter 和 Request【Web 服务要做的就是根据 Request 生成相应的 Response,并通过 ResponseWriter 返回给用户】,并使用 router 来实现动态路由【基于 Trie 树实现】,在 router 的基础上,进一步加入了 Group 使得路由可以被分组。此外,Gee 支持用户自定义的中间件,并在理论上可以无限拓展。中间件的行为类似于一个 HandlerFunc,它们会按照顺序执行非业务的逻辑,比如错误恢复或日志记录。


http://www.ppmy.cn/server/170341.html

相关文章

大语言模型中的 Token如何理解?

在大语言模型中,Token 是文本处理的基本单元,类似于“文字块”,模型通过将文本分割成Token来理解和生成内容。举一个形象一点的例子,可以理解为 AI 处理文字时的“最小积木块”。就像搭乐高时,每块积木是基础单位一样&…

【C】队列与栈的相互转换

栈与队列是两种特点相反的数据结构,一个特点是后进先出,一个特点是先进先出,但是他们之间是可以相互转换的。 目录 1 用队列实现栈 1) 题目解析 2) 算法解析 (1) 结构(MyStack) &#xff…

Amazon Lex:AI对话引擎重构企业服务新范式

在数字化转型浪潮中,智能交互能力正成为企业服务升级的核心竞争力。全球某头部电商平台曾面临日均10万的客服咨询压力,传统人工客服响应慢、成本高,而基于规则的传统聊天机器人又难以理解复杂需求。通过部署Amazon Lex,该企业仅用…

响应式数据ref()和reactive()的使用

官方网址:响应式基础 | Vue.js 在 Vue 3 中,ref 和 reactive 是用于创建响应式数据的两个核心 API。它们的用法和适用场景有所不同,以下是它们的详细说明和使用方法。 ref ref 用于创建一个响应式的基本类型或对象类型的数据。它会将数据包装…

《Restormer:高效Transformer架构用于高分辨率图像恢复》学习笔记

paper:2111.09881 GitHub:swz30/Restormer: [CVPR 2022--Oral] Restormer: 高分辨率图像修复的高效转换器。SOTA 用于运动去模糊、图像去模糊、去噪(高斯/真实数据)和去焦去模糊。 复现:Resto…

树莓派理想二极管电路分析

如果 Vin Vout,比如说 5.0V,PNP 晶体管以当前的镜像配置偏置。晶体管 U14 的 Vb 将为 5-0.6 4.4V,镜像配置意味着 Vg 也将为 4.4V. Vgs 为4.4-5.0 -0.6V。mosfet 将处于关闭状态(几乎打开)。如果 Vout 略低于 Vin&a…

【Gin-Web】Bluebell社区项目梳理5:投票功能分析与实现

本文目录 一、投票功能投票流程实现代码redis投票 一、投票功能 投票流程 首先我们要明确,就是 谁(哪个用户:userID) 给 哪个帖子(postID) 投了 什么票(赞成票or反对票)。 赞成票…

B. Skibidus and Ohio

time limit per test 1 second memory limit per test 256 megabytes Skibidus is given a string ss that consists of lowercase Latin letters. If ss contains more than 11 letter, he can: Choose an index ii (1≤i≤|s|−11≤i≤|s|−1, |s||s| denotes the curre…