7. 错误恢复

Kesa...小于 1 分钟golang

1. 错误处理

当前系统中,若某个位置触发了 panic,将会导致系统停机,这是不可接收的,所以需要引入错误处理机制。

因为已经实现了中间件机制,可以将错误处理作为中间件引入。

https://github.com/dreamjz/golang-notes/tree/main/books/7-days-golang/Gee/day7-recoveryopen in new window

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
    1. 调用runtime.Callers获取调用栈的程序计数器,跳过前3个(分别是runtime.Callers自身,tracedefer func
    2. 获取每个调用栈的函数位置

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

  1. https://geektutu.com/post/gee-day7.htmlopen in new window
上次编辑于:
评论
  • 按正序
  • 按倒序
  • 按热度
Powered by Waline v2.15.2