Golang

关注公众号 jb51net

关闭
首页 > 脚本专栏 > Golang > golang(gin)全局统一异常处理,并统一返回json

golang(gin)的全局统一异常处理方式,并统一返回json

作者:刘海琼宝宝

这篇文章主要介绍了golang(gin)的全局统一异常处理方式,并统一返回json,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教

golang(gin)全局统一异常处理,并统一返回json

定义Recover中间件

package handler

import (
	"awesomeProject/Result"
	"github.com/gin-gonic/gin"
	"log"
	"net/http"
	"runtime/debug"
)

func Recover(c *gin.Context) {
	defer func() {
		if r := recover(); r != nil {
			//打印错误堆栈信息
			log.Printf("panic: %v\n", r)
			debug.PrintStack()
			//封装通用json返回
			//c.JSON(http.StatusOK, Result.Fail(errorToString(r)))
			//Result.Fail不是本例的重点,因此用下面代码代替
			c.JSON(http.StatusOK, gin.H{
				"code": "1",
				"msg":  errorToString(r),
				"data": nil,
			})
			//终止后续接口调用,不加的话recover到异常后,还会继续执行接口里后续代码
			c.Abort()
		}
	}()
	//加载完 defer recover,继续后续接口调用
	c.Next()
}

// recover错误,转string
func errorToString(r interface{}) string {
	switch v := r.(type) {
	case error:
		return v.Error()
	default:
		return r.(string)
	}
}

使用Recover中间件

func main() {
	router := gin.Default()
	//注意 Recover 要尽量放在第一个被加载
	//如不是的话,在recover前的中间件或路由,将不能被拦截到
	//程序的原理是:
	//1.请求进来,执行recover
	//2.程序异常,抛出panic
	//3.panic被 recover捕获,返回异常信息,并Abort,终止这次请求
	router.Use(handler.Recover)

	router.GET("/ping", func(c *gin.Context) {
		// 无意抛出 panic
		var slice = []int{1, 2, 3, 4, 5}
		slice[6] = 6
	})

	router.Run(":8080") // listen and serve on 0.0.0.0:8080 (for windows "localhost:8080")

}

golang中异常处理问题

程序在运行过程中如果出现了问题,可以通过抛出异常、捕获异常来进行异常的处理,在golang中,异常的接口为error:

type error interface {
    Error() string
}

因此,只要一个结构体实现了Error() string方法,就是实现了error接口:

type MyError struct {

}
func (err *MyError)Error() string{
    return "this is MyError"
}

golang中可以通过panic来抛出异常,recover来捕获异常。如果不处理异常,最终会是程序整个退出

另外**捕获异常必须在defer中进行捕获,否则捕获异常recover不起作用**

type MyError struct {

}
func (err *MyError)Error() string{
    return "this is MyError"
}

func PanicError()  {
    fmt.Println("panic error")
    panic(MyError{})
}

func main() {
    defer func(){
        if err := recover() ; err != nil {

            fmt.Println("catch error ",err)
        }
    }()

    PanicError()
}

defer的机制,有点类似于java中的finall语句块

go中多个defer语句与defer的顺序相反执行,可以理解是将defer放入到一个先进后出的队列中

总结

以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。

您可能感兴趣的文章:
阅读全文