运维八一 运维八一
首页
运维杂记
编程浅尝
周积跬步
专栏
生活
关于
收藏
  • 分类
  • 标签
  • 归档
Source (opens new window)

运维八一

运维,运维!
首页
运维杂记
编程浅尝
周积跬步
专栏
生活
关于
收藏
  • 分类
  • 标签
  • 归档
Source (opens new window)
  • Go

    • 前言

    • Go基础知识

    • Go基本语法

    • 实战项目:简单web服务

    • 基本数据类型

    • 内置运算符

    • 分支和循环

    • 函数 function

    • 结构体 struct

    • 方法 method

    • 实战项目:跟踪函数调用链

    • 接口 interface

    • 并发 concurrency

    • 指针

    • 实战项目:实现轻量级线程池

    • 实战项目:实现TCP服务器

    • go常用包

    • Gin框架

      • gin入门
      • gin工作流程
        • 2. Gin工作流程
          • 2.1 gin核心概念
          • 2.2 请求生命周期
          • 2.3 gin源码
      • gin中间件
      • gin路由
      • gin请求
      • 数据绑定和校验
      • 响应返回
      • 路由分发
      • Cookie和Session
      • gin项目结构
      • GORM入门
      • 一对多关联查询
    • go随记

  • Python

  • Shell

  • Java

  • Vue

  • 前端

  • 编程浅尝
  • Go
  • Gin框架
lyndon
2022-06-23
目录

gin工作流程

# 2. Gin工作流程

# 2.1 gin核心概念

  • Engine 容器对象,整个框架的基础
  • Engine.trees 负责存储路由和handle方法的映射,采用类似字典树的结构
  • Engine.RouterGroup 其中的Handlers存储着所有中间件
  • Context 上下文对象 负责处理 请求和回应 ,其中的 handlers 是存储处理请求时中间件和处理方法的

image-20220623230955460

# 2.2 请求生命周期

image-20220623231021756

# 2.3 gin源码

gin.Default()

Default()跟New()几乎一模一样, 就是调用了gin内置的Logger(), Recovery()中间件

// Default返回一个已经附加了Logger和Recovery中间件的Engine实例
func Default() *Engine {
	debugPrintWARNINGDefault()
	engine := New() // 默认实例
	// 注册中间建,中间件的是一个函数,最终只要返回一个 type HandlerFunc func(*Context) 就可以
	engine.Use(Logger(), Recovery()) // 默认注册的两个中间件
	return engine
}
1
2
3
4
5
6
7
8

engine := New() 初始化

通过调用 gin.New() 方法来实例化 Engine容器 .

  • 1.初始化Engine
  • 2.将RouterGroup的Handlers(数组)设置成nil, basePath设置成 /
  • 3.为了使用方便, RouteGroup里面也有一个Engine指针, 这里将刚刚初始化的engine赋值给了RouterGroup的engine指针
  • 4.为了防止频繁的context GC造成效率的降低, 在Engine里使用了sync.Pool, 专门存储gin的Context
func New() *Engine {
	debugPrintWARNINGNew()
	// Engine 容器对象,整个框架的基础
	engine := &Engine{ // 初始化语句
	// Handlers 全局中间件组在注册路由时使用
	RouterGroup: RouterGroup{ // Engine.RouterGroup,其中的Handlers存储着所有中间件
	Handlers: nil,
	basePath: "/",
	root: true,
	},
	// 树结构,保存路由和处理方法的映射
	trees: make(methodTrees, 0, 9),
	}
	engine.RouterGroup.engine = engine
	return engine
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16

engine.Use() 注册中间件

  • gin框架中的中间件设计很巧妙,可以首先从最常用的 r := gin.Default() 的Default 函数开始看
  • 它内部构造一个新的 engine 之后就通过 Use() 函数注册了 Logger 中间件和 Recovery 中间件
  • Use()就是gin的引入中间件的入口了
  • 仔细分析这个函数, 不难发现Use()其实是在给RouteGroup引入中间件的.
func Default() *Engine {
    debugPrintWARNINGDefault()
    engine := New()
    engine.Use(Logger(), Recovery())  // 默认注册的两个中间件
    return engine
}
1
2
3
4
5
6

gin.use() 调用 RouterGroup.Use() 往 RouterGroup.Handlers 写入记录

func (engine *Engine) Use(middleware ...HandlerFunc) IRoutes {
    engine.RouterGroup.Use(middleware...)
    engine.rebuild404Handlers() //注册404处理方法
    engine.rebuild405Handlers() //注册405处理方法
    return engine
    }
    // 其中`Handlers`字段就是一个数组,用来存储中间件
    func (group *RouterGroup) Use(middleware ...HandlerFunc) IRoutes {
    group.Handlers = append(group.Handlers, middleware...)
    return group.returnObj()
}
1
2
3
4
5
6
7
8
9
10
11

组成一条处理函数链条 HandlersChain

- 也就是说,我们会将一个路由的中间件函数和处理函数结合到一起组成一条处理函数链条HandlersChain
- 而它本质上就是一个由HandlerFunc组成的切片
type HandlersChain []HandlerFunc
1
2
3

中间件的执行

其中 c.Next() 就是很关键的一步,它的代码很简单

从下面的代码可以看到,这里通过索引遍历 HandlersChain 链条,从而实现依次调用该路由的每一个函数(中间件或处理请求的函数),我们可以在中间件函数中通过再次调用 c.Next() 实现嵌套调用(func1中调用func2;func2中调用func3)

func (c *Context) Next() {
    c.index++
    for c.index < int8(len(c.handlers)) {
        c.handlers[c.index](c)
        c.index++
    }
}
1
2
3
4
5
6
7

r.GET() 注册路由

r.GET("/", func(c *gin.Context) {
    c.String(http.StatusOK, "hello World!")
})
1
2
3

通过Get方法将路由和处理视图函数注册

上次更新: 2022/06/23, 23:56:29
gin入门
gin中间件

← gin入门 gin中间件→

最近更新
01
ctr和crictl显示镜像不一致
03-13
02
alpine镜像集成常用数据库客户端
03-13
03
create-cluster
02-26
更多文章>
Theme by Vdoing | Copyright © 2015-2024 op81.com
苏ICP备18041258号-2
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式