Gin —— 一个Golang微框架

Posted 小米运维

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Gin —— 一个Golang微框架相关的知识,希望对你有一定的参考价值。

本篇文章介绍了gin的特点,以及其自定义中间件的原理和方法。

封面图片来自于:pixabay kellepics


    Gin 是一个 golang 的 web 框架,

    封装优雅,文档完备,已发布 1.2 版本。

    具有以下特点:

  • 快,基于 radix tree 路由,内存占用少,无反射;

  • 自定义中间件,易于扩展;

  • 分组路由,更好的组织路由结构;

  • 参数绑定,解析和验证请求数据,可自定义验证方法;

  • 错误管理,提供收集 http 请求过程中所有错误的便捷方式;

  • 内置多种格式渲染。

巧用中间件


支持自定义中间件是当时选择 gin 开发服务的主要原因之一。gin 中间件分为全局中间件、群组中间件和单路由中间件三种。


func main() {
    router := gin.New()    
   //全局中间件    router.Use(GlobalMiddleware())    
   
   //群组中间件    api := router.Group("/v1/api", GroupMiddleware())    
   
   //单路由中间件    api.GET("/health", SingleMiddleware(), func(ctx *gin.Context) {        ctx.String(http.StatusOK, "ok")    })    router.Run(":8080") }


完成路由设置后,每个注册的路由规则都会绑定一个 middleware chain,其中最后一个中间件即为业务处理逻辑。接收到的 http 请求,匹配到相应的路由规则后会递归执行 middleware chain,如果中间件 abort,将不会执行后续中间件。



下面简单介绍几种巧用中间件的方法


做 before request 和 after request 的统一处理


使用中间件可以在业务逻辑的前后做很多定制处理。

func RequestMiddleware() gin.HandlerFunc {    
   return func(ctx *gin.Context) {        fmt.Println("before request")        ctx.Next()        fmt.Println("after request")    } }
   
任性 panic,规范返回结果

通过自定义中间件,可以捕获 http 请求中的异常并恢复,保证服务始终可用。此外,利用自定义错误类型,在处理 http 请求过程中能任意抛出错误,通过中间件的统一捕获,进而简化程序并规范返回结果。

type StatusError struct {
    StatusCode int
    Msg        string}
func (se *StatusError) Error() string {    
   return fmt.Sprintf("status_code:%d, msg:%s", se.StatusCode, se.Msg) }
func BadRequestStatusError(msg ...string) StatusError {    status_err := StatusError{        StatusCode: http.StatusBadRequest,        Msg:        "bad request",    }    
   if len(msg) > 0 {        status_err.Msg = msg[0]    }    
   return status_err }
   
func abortWithStatusMsg(ctx *gin.Context, status int, msg string) {    ctx.String(status, msg)    ctx.Abort() }
func RecoveryMiddleware(out io.Writer) gin.HandlerFunc {    logger := log.New(out, "\n\n\x1b[31m", log.LstdFlags)    
   return func(ctx *gin.Context) {        
       defer func() {            
           if err := recover(); err != nil {                
               if e, ok := err.(StatusError); ok {                    
                   //自定义错误,业务逻辑故意抛出的,返回统一格式数据                    abortWithStatusMsg(ctx, e.StatusCode, e.Msg)                    
                   return                }                
                   
               //打印堆栈                stack := make([]byte, 1024*8)                stack = stack[:runtime.Stack(stack, false)]                httprequest, _ := httputil.DumpRequest(ctx.Request, false)                logger.Printf("[Recovery] panic recovered:\n%s\n%s\n%s", string(httprequest), err, stack)                
               //异常报警                //report to sentry                //返回统一格式数据                abortWithStatusMsg(ctx, http.StatusInternalServerError, "Server error, please contact admin!")            }        }()        ctx.Next()    } }
         
func main() {    router := gin.New()    
   var DefaultWriter io.Writer = os.Stdout    router.Use(RecoveryMiddleware(DefaultWriter))    router.GET("/", func(ctx *gin.Context) {        
       panic(BadRequestStatusError("this is a test"))    })    router.Run(":8080") }

分组路由绑定不同的登录规则


通过多个中间件实现不同的登录鉴权方式,并绑定到相应的路由分组,可以很方便的实现同一系统不同路由使用不同鉴权。

func main() {
    router := gin.Default()

    v1 := router.Group("/v1", V1AuthMiddleware())
    v2 := router.Group("/v2", V2AuthMiddleware())

    router.Run(":8080")
}


在使用中间件的过程中还需注意以下两点:


  • 注册中间件之前设置的路由,将不受注册中间件的影响。

  • 中间件 abort 时,需立即 return,才不会执行本中间件后续的代码。


其他Point


1、gin 提供了两种 model binding 方式以验证请求的数据,分别是 Must Bind 和 Should Bind。如果验证出错,Must Bind 会返回错误并且

ctx.AbortWithError(400,err).SetType(ErrorTypeBind),Content-Type会被设置成text/plain; charset=utf-8;而 Should Bind 只会返回错误,开发者需自行处理。


2、利用自定义参数验证方法,抽象出常用的验证方式,便于代码复用。


3、利用gin.Context.Errors可以收集 http 请求过程中所有错误,统一处理。


4、在 debug 模式下,请求会实时加载模板便于开发调试;而 release 模式会直接从内存中获取模板以提升服务性能。


5、可以使用 go-swagger 生成 API 自动化文档。


总结


如果你也喜欢自定义中间件,想利用优秀的开源模块堆积木式地搭建自己的 http 服务,gin 会是一个不错的选择。




长按指纹,关注传说中的小米运维



以上是关于Gin —— 一个Golang微框架的主要内容,如果未能解决你的问题,请参考以下文章

Golang 微框架 Gin 简介

GoLang -- Gin框架

golang gin 学习系列

golang 都有哪些比较稳定的 web 开发框架

11.2Go gin

Golang Gin 框架之中间件