概念

  1. 一个完整的系统可能包括鉴权认证、权限管理、安全检查、日志记录等多维度的系统支持。
  2. 中间件位与服务器和实际业务处理程序之间,其含义就相当于在请求和具体的业务处理逻辑之间增加某些操作,这种以额外增加的方式不会影响编码的效率,也不会侵入到框架中。

中间件的位置和角色示意图

自定义一个中间件

  • gin中间件的类型是函数,有两条标准
  1. func函数
  2. 返回值是HandlerFunc类型
  • 案例:定义一个log日志的中间件,打印path和Method
package main

import (
"fmt"
"github.com/gin-gonic/gin"
) func main() {
router := gin.New() // 全局使用自定义的中间件
router.Use(Logger()) router.GET("/hello", HelloHandle)
// 单个接口使用自定义的中间件
router.GET("/index", RemoteAddr(), IndexHandle) router.Run(":8000")
}
func Logger() gin.HandlerFunc {
// 打印请求路径和方法的中间件
return func(ctx *gin.Context) {
fmt.Println(ctx.FullPath(), ctx.Request.Method)
}
}
func RemoteAddr() gin.HandlerFunc {
// 打印远程地址的中间件
return func(context *gin.Context) {
fmt.Println(context.Request.RemoteAddr)
}
}
func HelloHandle(ctx *gin.Context) {
ctx.Writer.Write([]byte("hello world!"))
}
func IndexHandle(ctx *gin.Context) {
ctx.Writer.Write([]byte("hello index!"))
}

context.Next函数

  • contentx.Next函数可以将中间件代码的执行顺序一分为二,Next函数之前的代码在请求处理之前执行,当执行到Next函数时会中断向下执行,去执行具体的业务逻辑代码,当业务逻辑代码执行完成后,在继续执行Next函数后面的代码。
  • 案例
package main

import (
"fmt"
"github.com/gin-gonic/gin"
"net/http"
) func main() {
router := gin.Default() // 全局使用自定义的中间件
router.Use(Logger()) router.GET("/hello", HelloHandle)
// 单个接口使用自定义的中间件
router.GET("/index", RemoteAddr(), IndexHandle) router.Run(":8000")
}
func Logger() gin.HandlerFunc {
// 打印请求路径和方法的中间件
return func(ctx *gin.Context) {
fmt.Println(ctx.FullPath(), ctx.Request.Method)
fmt.Println("状态码", ctx.Writer.Status())
ctx.Next()
fmt.Println("状态码", ctx.Writer.Status())
}
}
func RemoteAddr() gin.HandlerFunc {
// 打印远程地址的中间件
return func(context *gin.Context) {
fmt.Println(context.Request.RemoteAddr) // 中断执行,去执行接口业务代码,接口业务执行完毕后在回来执行context.Next()后面的代码
context.Next() status := context.Writer.Status()
fmt.Println("状态码:", status)
}
}
func HelloHandle(ctx *gin.Context) {
ctx.String(http.StatusNotFound, "404 not found")
fmt.Println("hello接口执行完了")
}
func IndexHandle(ctx *gin.Context) {
fmt.Println("index函数执行了")
ctx.Writer.Write([]byte("hello index!"))
}

gin框架中中间件的编写与使用的更多相关文章

  1. 在gin框架中使用JWT

    在gin框架中使用JWT JWT全称JSON Web Token是一种跨域认证解决方案,属于一个开放的标准,它规定了一种Token实现方式,目前多用于前后端分离项目和OAuth2.0业务场景下. 什么 ...

  2. golang gin框架中实现一个简单的不是特别精确的秒级限流器

    起因 看了两篇关于golang中限流器的帖子: Gin 开发实践:如何实现限流中间件 常用限流策略--漏桶与令牌桶介绍 我照着用,居然没效果-- 时间有限没有深究.这实在是一个很简单的功能,我的需求是 ...

  3. gin框架中的路由

    基本路由 gin框架中采用的路由库是基于httrouter做的 地址为:https://github.com/julienschmidt/httprouter httprouter路由库 点击查看代码 ...

  4. gin框架中请求路由组的使用

    1. gin框架中可以使用路由组来实现对路由的分类 package main import "github.com/gin-gonic/gin" func main() { rou ...

  5. gin框架中的中间件

    全局中间件 所有请求都经过此中间件 中间件中设置值 func MiddleWare() gin.HandlerFunc { return func(context *gin.Context) { t ...

  6. Gin框架中文文档

    Gin 是一个 go 写的 web 框架,具有高性能的优点.官方地址:https://github.com/gin-gonic/gin 带目录请移步 http://xf.shuangdeyu.com/ ...

  7. 【解决了一个小问题】gin框架中出现如下错误:"[GIN-debug] [WARNING] Headers were already written. Wanted to override status code 400 with 500"

    POST到数据到一条gin框架的接口后,客户端收到400错误,并且返回了业务中返回的"decode json fail". 关键代码是: func report(c *gin.Co ...

  8. golang gin框架中实现大文件的流式上传

    一般来说,通过c.Request.FormFile()获取文件的时候,所有内容都全部读到了内存.如果是个巨大的文件,则可能内存会爆掉:且,有的时候我们需要一边上传一边处理. 以下的代码实现了大文件流式 ...

  9. gin框架中使用jwt

    生成解析token 如今有很多将身份验证内置到API中的方法 -JSON Web令牌只是其中之一.JSON Web令牌(JWT)作为令牌系统而不是在每次请求时都发送用户名和密码,因此比其他方法(如基本 ...

随机推荐

  1. [Elasticsearch] ES 的Mapping 设计在实际场景中应用

    背景 项目中有个需求是需要几个字段作为标签,统计各个标签的文档数量,同时支持分词后的全文检索功能. 原有的mapping设计: curl -XPUT http://ip:9200/meta_es_me ...

  2. IDEA常用设置及插件

    设置 1.设置打开后不直接进入项目 IDEA默认打开时会直接进入上次打开的目录,有的时候加载很长时间,但这个时候可能我们并不是要打开这个项目,这里有一个设置,在如图的位置,去掉勾选,即可设置打开后不直 ...

  3. Linux启动、停止宝塔

    启动 /etc/init.d/bt start 停止 /etc/init.d/bt stop

  4. Spring Boot程序插入时间和MySQL数据库显示时间不一样(设置数据库时区)

    首先查看数据库时区 show variables like "%time_zone%"; # 设置全局时区 mysql> set global time_zone = '+8 ...

  5. c++11之algorithm算法库新增is_sorted和sorted_until

    0.时刻提醒自己 Note: vector的释放 1.is_sorted 1.1 功能 检查 [first, last) 中的元素是否以不降序排序 1.2 异常 若算法无法分配内存,则抛出 std:: ...

  6. codeforce A. 2Char(水题,暴力)

    今晚发了个蛇精病,然后CF了,第一题这好难啊,然而水题一个,暴力飘过. 链接http://codeforces.com/contest/593/problem/A: 题意比较难懂吗?傻逼百度都翻译不对 ...

  7. MCU变量加载过程

    前言 在开发mcu代码的时候经常会有些疑惑,变量是怎么在编译之后进入单片机的ram区的呢,特别是在使用keil开发的时候.后来在接触gcc编译器和自研的mcu后,终于明白了这个问题.实际上变量编译后被 ...

  8. [opencv]findcoutours函数使用

    轮廓是定义或限定形状或对象的边或线,是机器视觉中的常用的概念,多用于目标检测.识别等任务. 关于OpenCV轮廓操作,尤其是级别及如何使用轮廓级别进行筛选等问题,相关文章比较少,正好最近用到,因此将其 ...

  9. 使用.NET 6开发TodoList应用(17)——实现数据塑形

    系列导航及源代码 使用.NET 6开发TodoList应用文章索引 需求 在查询的场景中,还有一类需求不是很常见,就是在前端请求中指定返回的字段,所以关于搜索的最后一个主题我们就来演示一下关于数据塑形 ...

  10. CSS基础 结构伪类选择器 last-child、first-child和nth-of-type的使用方法

    一.通过伪类选择器查找单个标签元素html结构 <div> <a herf='#'>导航1</a> <a herf='#'>导航2</a> ...