大家好,我是渔夫子

本文咱们介绍下recover在gin框架中的利用。
首先,在golang中,如果在子协程中遇到了panic,那么主协程也会被终止。如下:

package mainimport (    "github.com/gin-gonic/gin")func main() {    r := gin.Default()    // 在子协程中引起panic,主协程也会退出    go func() {        panic("hello world")    }()        // Listen and Server in 0.0.0.0:8080    r.Run(":8080")}

panic被形容为不可解决的谬误。在web服务中就是服务会解体。当然,这在生产环境下是不可承受的。那么,如何可能做到产生panic时技能捕捉该panic又能让服务持续衰弱运行呢?

这就是golang中提供的recover函数了。recover函数可能捕捉Panic谬误并恢复程序的失常运行。
接下来,咱们看下recover函数在gin框架中是如何利用的。

首先,要提到的就是gin框架中的recovery中间件。在gin中,是通过应用该中间件来捕捉panic,并保障服务不down机的。 如果应用gin.Default()函数进行构建gin对象,那么默认就注册了Recovery中间件。

func Default() *Engine {    debugPrintWARNINGDefault()    engine := New()    //  注册了Recovery中间件    engine.Use(Logger(), Recovery())    return engine}

其次,咱们来看下Recovery()中间件都做了些什么。

Recovery()函数定义如下:

func Recovery() HandlerFunc {    return RecoveryWithWriter(DefaultErrorWriter)}

这里的DefaultErrorWriter是默认的输入端,即os.Stderr。即指谬误的输入到什么中央。

接下来看RecoveryWithWriter函数中的实现

// RecoveryWithWriter returns a middleware for a given writer that recovers from any panics and writes a 500 if there was one.func RecoveryWithWriter(out io.Writer, recovery ...RecoveryFunc) HandlerFunc {    if len(recovery) > 0 {        return CustomRecoveryWithWriter(out, recovery[0])    }    return CustomRecoveryWithWriter(out, defaultHandleRecovery)}

这里有一个参数是defaultHandleRecovery,咱们看下它的实现:

func defaultHandleRecovery(c *Context, err any) {    c.AbortWithStatus(http.StatusInternalServerError)}

就是写入了一个代表外部服务器谬误的状态码500,并完结了本次申请。

这里关键点是CustomRecoveryWithWriter的实现,代码很长,咱们分段来看。如下:

次要分三局部:

  • 将日志输入到out中,这里是上述提到的DefaultErrorWriter,即os.Stderr。
  • defer提早执行局部。
  • c.Next()失常申请处理器局部。

这里须要留神的点就是:

  • recover函数须要再defer中调用。因为defer是在函数返回时才调用,所以当产生panic时会导致函数返回,这样能力捕捉panic。
  • 作为中间件运行,阐明每次申请的处理器都被中间件包装了,也就相当于每个申请处理器都有这个defer函数。
  • 在defer函数中,如果捕捉了panic,则将panic的具体具体记录下来,能够发送到指定的输入中,即函数中指定的out参数(默认是os.Stderr),也能够指定其余的文件或Sentry等。

在gin中,正是该中间件的利用,确保了web服务的健壮性。当然,其余的web框架也有同样的机制,实现原理也是一样的。

公众号:Go学堂

特地阐明:你的关注,是我写下去的最大能源。点击下方公众号卡片,间接关注。关注送《100个go常见的谬误》pdf文档、经典go学习材料。