7. 错误恢复
...小于 1 分钟
1. 错误处理
当前系统中,若某个位置触发了 panic,将会导致系统停机,这是不可接收的,所以需要引入错误处理机制。
因为已经实现了中间件机制,可以将错误处理作为中间件引入。
https://github.com/dreamjz/golang-notes/tree/main/books/7-days-golang/Gee/day7-recovery
1.1 recovery
package gee
import (
"fmt"
"log"
"net/http"
"runtime"
"strings"
)
func Recovery() HandlerFunc {
return func(c *Context) {
defer func() {
if err := recover(); err != nil {
msg := fmt.Sprintf("%s", err)
log.Printf("%s\n\n", trace(msg))
c.Fail(http.StatusInternalServerError, "Internal Server Error")
}
}()
c.Next()
}
}
func trace(msg string) string {
var pcs [32]uintptr
n := runtime.Callers(3, pcs[:])
var sb strings.Builder
sb.WriteString(msg + "\nTraceback:")
for _, pc := range pcs[:n] {
fn := runtime.FuncForPC(pc)
file, line := fn.FileLine(pc)
sb.WriteString(fmt.Sprintf("\n\t%s:%d", file, line))
}
return sb.String()
}
Reocvery
:捕获异常并恢复,返回错误信息,并记录调用栈trace
:- 调用
runtime.Callers
获取调用栈的程序计数器,跳过前3个(分别是runtime.Callers
自身,trace
,defer func
) - 获取每个调用栈的函数位置
- 调用
1.2 gee
func Default() *Engine {
engine := New()
engine.Use(Logger(), Recovery())
return engine
}
1.2 Demo
func main() {
r := gee.Default()
r.GET("/", func(c *gee.Context) {
c.String(http.StatusOK, "Welcome")
})
r.GET("/panic", func(c *gee.Context) {
names := []string{}
c.String(http.StatusOK, names[1])
})
r.Run(":8000")
}
$ curl http://localhost:8000/panic
{"message":"Internal Server Error"}
$ curl http://localhost:8000/
Welcome
Reference
Powered by Waline v2.15.2