深入浅出-Gin-生命周期

1,083 阅读2分钟

Gin是一个用Go编写的web框架,我们来看一下Gin的请求生命周期。有助于了解Gin的执行原理和开发。

1、Gin服务执行流程

启动一个简单的的Gin http服务:

package main

import "github.com/gin-gonic/gin"

func main() {
    // 创建 Gin Engine 实例
    r := gin.Default()

    // 设置请求 URI /ping 的路由及响应处理函数
    r.GET("/ping", func(c *gin.Context) {
        c.JSON(200, gin.H{
            "message": "pong",
        })
    })

    // 启动 Web 服务,监听端口,等待 HTTP 请求到并生成响应
    r.Run() // 监听并在 0.0.0.0:8080 上启动服务
}

通过执行go run main.go命令来运行代码,它会启动一个阻塞进程监听并等待HTTP请求:

从代码中我们看出通过Gin实现一个最简单的Web服务器,只需要三个步骤:

  1. 创建Gin实例
  2. 注册路由及处理函数
  3. 启动Web服务

执行流程图如下:

2、Gin生命周期

2.1、创建Gin实例

Gin实例创建通过Gin.Default()方法实现,其定义如下:

func Default() *Engine {
    //调试模式日志输出
    debugPrintWARNINGDefault()
    //创建一个gin框架实例
    engine := New()
    //注册中间件,中间件是一个函数,最终只要返回一个type HandlerFunc func(*Context)就可以
    engine.Use(Logger(), Recovery())
    return engine
}

Default()方法实现如下功能:

  1. 创建Gin框架对象Engine
  2. 配置Gin默认的中间件
  3. 返回Gin框架对象

2.2、注册路由

以 gin.GET 为例,开展源码如下:

// GET is a shortcut for router.Handle("GET", path, handle).
func (group *RouterGroup) GET(relativePath string, handlers ...HandlerFunc) IRoutes {
    return group.handle(http.MethodGet, relativePath, handlers)
}

路由注册,实际上是调用了RouterGroupGet方法,RouterGroup实现了IRoutes interface, RouterGroup主要提供路由注册功能。

type RouterGroup struct {
    Handlers HandlersChain
    basePath string
    engine   *Engine
    root     bool
}

2.3、接收请求并响应

Gin实例化和路由注册工作后,然后进入Gin声明周期外围功能分析,Gin到底是如何启动Web服务,监听HTTP请求处理函数生成响应的,这些工作是从Gin.Run实现的。

func (engine *Engine) Run(addr ...string) (err error) {
    defer func() { debugPrintError(err) }()

    address := resolveAddress(addr)
    debugPrint("Listening and serving HTTP on %s\n", address)
    //执行http包的ListenAndServe方法,启动路由
    //engine实现了http.Handler接口,所以在这里作为参数穿进去
    err = http.ListenAndServe(address, engine)
    return
}

gin.Runnet/http标准库http.ListenAndServe的简写,功能是将路由连接到http.Server启动并监听HTTP请求。

本文正在参加技术专题18期-聊聊Go语言框架