golang http 中间件

源码链接

golang的http中间件的实现 首先实现一个http的handler接口

type Handler interface {
    ServeHTTP(ResponseWriter, *Request)
}

type Router struct {
    route map[string]Handle
}

func (r *Router) ServeHTTP(w http.ResponseWriter, req *http.Request) {
}

通过函数包裹的方式实现

中间件v1.0

1.通过匿名函数 将handler包裹起来 然后再 调用传进来的handler。在执行传进来的参数之前
就可以做到记录日志 等一些中间件的功能

2.如果有多个中间件 那么就多个函数 一层一层包裹

func withMiddle(h Handle) Handle {
    return func(writer http.ResponseWriter, request *http.Request) {
        t := time.Now()
        defer func() {
            log.Println("time spend is ", time.Since(t))
        }()
        h(writer, request)
    }
}

func (r *Router) Register1(route string, f Handle) {
    r.route[route] = withMiddle(f)
}

func (r *Router) Register2(route string, f Handle) {
    r.route[route] = withMiddLog(withMiddTime(f))
}

Register("/bench", func(writer http.ResponseWriter, request *http.Request) {
    time.Sleep(time.Second)
    fmt.Println("bench sleep 1 second")
})

中间件v1.1

注册的时候 可以更加简化一些 通过匿名函数的方式 当然这种方式没有传递参数
只是作为演示用的

func (r *Router) Register(route string, f HandlerFunc) {
    r.route[route] = withMiddLog(withMiddTime(func(writer http.ResponseWriter, request *http.Request) {
        f()
    }))
}

中间件v2.0

针对中间件v1.1中的没法传递 http中的读写参数的问题 可以封装一个context
将http的读写参数都包裹进来 这样就可以很方便的处理读写了

func (r *Server) Register(route string, f HandlerFunc) {
    r.route[route] = withMiddLog(withMiddTime(func(writer http.ResponseWriter, request *http.Request) {
        f(r.createContext(writer, request))
    }))
}
r.Register("/bench", func(c *Context) {
        time.Sleep(time.Second)
        fmt.Println("bench sleep 1 second")
        c.Writer.Write([]byte("hello!\r\n"))
    })

golang框架gin中的实现

中间件v3.0

核心理念是将中间件和最后的函数 一视同仁 。通过一个for循环遍历具体的可以参考代码

func (c *Context) Next() {
    c.index++
    //for中的index++是为了退出循环 否则没法退出
    for ; c.index < len(c.middle); c.index++ {
        c.middle[c.index](c)
    }
}

func withMiddTime() HandleContext {
    return func(c *Context) {
        t := time.Now()
        defer func() {
            fmt.Println("withMiddTime end time", time.Since(t))
        }()
        fmt.Println("withMiddTime start ", time.Since(t))
        c.Next()
    }
}
func (s *Server) Register(path string, f ...HandleContext) {
    handleNew := make([]HandleContext, 0, len(s.handle)+len(f))
    handleNew = append(handleNew, s.handle...)
    handleNew = append(handleNew, f...)
    s.routeHandler(path, func(writer http.ResponseWriter, request *http.Request) {
        s.createContext(writer, request, handleNew).Next()
    })
}

golang http 中间件的更多相关文章

  1. 基于gin的golang web开发:中间件

    gin中间件(middleware)提供了类似于面向切面编程或路由拦截器的功能,可以在请求前和请求之后添加一些自定义逻辑.实际开发中有很多场景会用到中间件,例如:权限验证,缓存,错误处理,日志,事务等 ...

  2. 在 Golang 中实现一个简单的Http中间件

    本文主要针对Golang的内置库 net/http 做了简单的扩展,通过添加中间件的形式实现了管道(Pipeline)模式,这样的好处是各模块之间是低耦合的,符合单一职责原则,可以很灵活的通过中间件的 ...

  3. golang程序设计:Go middleware中间件以及Gin 中间件分析

    先从业务开发角度出发,来逐渐引出中间件. 一.刚开始时业务开发 开始业务开发时,业务需求比较少. 当我们最开始进行业务开发时,需求不是很多. 第一个需求产是品向大家打声招呼:"hello w ...

  4. Golang Web入门(3):如何优雅的设计中间件

    摘要 在上一篇文章中,我们已经可以实现一个性能较高,且支持RESTful风格的路由了.但是,在Web应用的开发中,我们还需要一些可以被扩展的功能. 因此,在设计框架的过程中,应该留出可以扩展的空间,比 ...

  5. Golang进阶,揉碎数据库中间件,干货满满!

    目录 必读 一.Centos7.Mac安装MySQL 二.主从复制原理 2.1.基于binlog_filename + position 2.2.基于GTID 三.my.cnf 四.测试SQL 五.中 ...

  6. 【get√】golang新手理解了一点点gin框架的中间件

    1.通过use()来使用多个中间件 router := gin.New() router.Use( middleware1, middleware2) 2.中间件的典型实现 func Logger() ...

  7. golang实现路由中间件middleware

    registerHandlers.go package router import ( "../ctrl" "../funcs" "github.co ...

  8. Golang友团无闻Go语言Web基础视频教程

    教程内容:GO语言资料Golang友团无闻Go语言编程基础Golang友团无闻Go语言Web基础教程 Go语言Web基础教程列表:[Go Web基础]12Go Web 扩展学习.mp4[Go Web基 ...

  9. Ubuntu14.04+RabbitMQ3.6.3+Golang的最佳实践

    目录 [TOC] 1.RabbitMQ介绍 1.1.什么是RabbitMQ?   RabbitMQ 是由 LShift 提供的一个 Advanced Message Queuing Protocol ...

随机推荐

  1. redis--StringRedisTemplate和RedisTemplate区别

    StringRedisTemplate: 1).只能存储string类型的值,因此不能存储如对象 2).序列化为string,如: RedisTemplate: 1).可以存储任意类型,含对象. 2) ...

  2. 微服务的.NET Core示例框架

    eShopOnContainers 是一个基于微服务的.NET Core示例框架 https://www.cnblogs.com/fengqingyangNo1/p/9438428.html 找到一个 ...

  3. java jmap

    jmap : 命令用于生成堆转储快照.它还可以查询finalize执行队列.Java堆和永久代的详细信息,如空间使用率.当前用的是哪种收集器等. 命令格式: jmap [option] vmid op ...

  4. Eclipse 在桌面创建快捷方式打开工作区

    创建eclipse快捷的方式,并Copy到桌面. 打开快捷方式的属性窗口,在[目标]栏,增加参数 –data 你的工作区目录

  5. swift 第三方库迁移错误解决“Use Legacy Swift Language Version” (SWIFT_VERSION) is required to be configured correctly for targets which use Swift. Use the [Edit > Convert > To Current Swift Syntax…] menu to choo

    先看看错误提示 这里Alamofire库报错,原因打开工程会Xcode会提示你覆盖到最新的3.0版本.但是仍然有些框架会出现一些问题 解决办法: 选择Pods - ReactiveCocoa - Sw ...

  6. ubuntu和window之间如何共享文件

    参考网上的自己动手实现共享文件: 1.打开虚拟机进入ubuntu系统,先安装增强功能包 2.安装完重启虚拟机后,在window下创建一个专门用来共享的文件夹 3.切换到ubuntu系统,在设备的共享文 ...

  7. Gradle项目构建(1)——Gradle的由来

    一.项目自动构建介绍 作为Java的开发者对eclipse都非常熟悉,其实eclipse就是居于ant来构建项目的,我们先来看看为什么需要自动化构建项目. 1.为什么我们要自动化构建项目 可以假设我们 ...

  8. 我们为什么要看《超实用的HTML代码段》

    不知道自己HTML水平如何,不知道HTML5如何进化?看这张图 如果一半以上的你都不会,必须看这本书,阿里一线工程师用代码和功能页面来告诉你每一个技术点. 都会一点,但不知道如何检验自己,看看本书提供 ...

  9. 用Python完成根据日期计算是星期几

    import datetime def week(year,month,day): someday=dayetime.date(year,month,day) result={ "0&quo ...

  10. HDU 5095 Linearization of the kernel functions in SVM (坑水)

    比较坑的水题,首项前面的符号,-1,+1,只有数字项的时候要输出0. 感受一下这些数据 160 0 0 0 0 0 0 0 0 -10 0 0 0 0 0 0 0 0 10 0 0 0 0 0 0 0 ...