如何在Golang中实现中间件-Part 1

当使用net/http包实现服务的时候,一般使用的是如下的两中处理方式:

  • http.HandleFunc
  • http.Handle

http.HandleFunc

分析

当使用这种方式的时候,其接受两个参数,一个是字符串格式的匹配符(pattern),另外一个就是func(ResponWrite, *Request),
因此只要我们的中间件中返回该类型,那么中间件就是可以实现的

func main(){
http.HandleFunc("/", Hello)
http.ListenAndServe(":8080", nil)
} func Hello(w http.ResponseWriter, r *http.Request) {
fmt.Print("hello")
}

当我们运行如上的程序的时候,就会打印出hello这个结果,说明我们的写法是没有问题的

实现

接下来,我们需要定义我们的中间件,它需要接收一个` http.HandlerFunc`类型,并且返回一个http.HandlerFunc这样才能被使用

func MyMiddleware(next http.HandlerFunc)http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
fmt.Println("middleware")
//doSomethinds
next.ServeHTTP(w,r)
}
}

由于调用next.ServeHTTP(w, r)等效于调用next(w, r),处理完后会返回响应w,最终相应会传递到最外层的匿名函数,从而最终会返回到客户端

http.Handle

分析

http.Handle接受两个参数,一个是匹配符,另外一个是http.Handler,当我们查看源码的时候,发现其是一个接口类型

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

因此我们最终得返回一个实现了该接口的类型,假设我们首先定义一个新的结构体,并为其添加一个`ServiceHTTP`

解决

type MyResponse struct {
next http.Handle
Code int64
Msg string
Errors []string
Data map[string]interface{}
} func (res *MyResponse)ServeHTTP(w http.ResponseWriter, r *http.Request) { result, err := json.Marshal(res)
if err 大专栏  Golang Middleware Part 1 · To Be A Better Mancolor:#f92672">!= nil {
fmt.Println(err.Error())
}
w.Write(result)
}

紧接着我们定义两个处理函数

func Hello(w http.ResponseWriter, r *http.Request)  {
fmt.Println("hello")
} func World(w http.ResponseWriter, r *http.Request) {
fmt.Println("world")
}

然后在主函数里面进行调用

    var res = new(MyResponse)
res.next = Hello
http.Handle("/hello", res)
res.next = World
http.Handle("/world", res)
http.ListenAndServe(":8080", nil)

然后你会发现诡异的事情发生了,无论你访问哪一个路由地址,最终打印的都只是world,这是因为Golang是一门静态的预编译语言,编译完成后,`res`总的next属性
将会永远指向World的地址,

因此我们可以做一个映射,将next变成map类型,但是想一想,如果路由非常多的话,那将是一件多可怕的事情,因此我们需要另辟蹊径,有没有其他的办法可以实现,查看源码我们可以发现
之前我们所使用过的http.HandleFunc与之相对应的还有一个类型http.HandlerFunc,该类型实现了ServerHTTP方式

type HandlerFunc func(ResponseWriter, *Request)

// ServeHTTP calls f(w, r).
func (f HandlerFunc) ServeHTTP(w ResponseWriter, r *Request) {
f(w, r)
}

接下来我们利用Goalng中的强制类型转换,就可以写出如下的中间件

func MySencondMiddleware(next http.HandlerFunc) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
//do somethings
next.ServeHTTP(w, r)
})
}

Please enable JavaScript to view the comments powered by Disqus.

Golang Middleware Part 1 · To Be A Better Man的更多相关文章

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

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

  2. golang实现路由中间件middleware

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

  3. golang 依赖控制反转(IoC)

    主流开发语言,为了达到项目间的低耦合,都会借助IoC框架来实现.即抽象和实现分离,使用抽象层,不用关心这些抽象层的具体实现:抽象层的实现,可以独立实现.现在比较流行的领域驱动设计(ddd),为了达到将 ...

  4. golang中Context的使用场景

    golang中Context的使用场景 context在Go1.7之后就进入标准库中了.它主要的用处如果用一句话来说,是在于控制goroutine的生命周期.当一个计算任务被goroutine承接了之 ...

  5. Golang 微框架 Gin 简介

    框架一直是敏捷开发中的利器,能让开发者很快的上手并做出应用,甚至有的时候,脱离了框架,一些开发者都不会写程序了.成长总不会一蹴而就,从写出程序获取成就感,再到精通框架,快速构造应用,当这些方面都得心应 ...

  6. Golang处理数据库的nil数据

    在用golang获取数据库的数据的时候,难免会遇到可控field.这个时候拿到的数据如果直接用string, time.Time这样的类型来解析的话会遇到panic. 那么如何处理这个问题呢,第一个出 ...

  7. Go实战--golang中使用JWT(JSON Web Token)

    http://blog.csdn.net/wangshubo1989/article/details/74529333 之前写过关于golang中如何使用cookie的博客: 实战–go中使用cook ...

  8. golang 请求带验证信息的坑

    最近用golang 和python对接接口,由于之前验证那块没有设置好,然后又为了进度,最近决定用http自带的basic 验证, php的代码很快就验证通过了 /** * @param $url * ...

  9. Learn golang: Top 30 Go Tutorials for Programmers Of All Levels

    https://stackify.com/learn-go-tutorials/ What is Go Programming Language? Go, developed by Google in ...

随机推荐

  1. protobuf 的enum与string转换

    c/c++ enum 介绍 说起c/c++ 的enum,比起python 真的是方便简洁 enum type{ type1 = 0, type2 } enum的元素对应的int 默认从0 开始依次增加 ...

  2. mysql6数据库安装与配置

    详细步骤可以参考这篇文章 https://www.cnblogs.com/duguangming/p/10623520.html 1.下载并打开mysql6数据库安装文件 2.默认点击下一步 3.点击 ...

  3. 108.生成和下载csv文件

    生成CSV文件 有时候我们做的网站,需要将一些数据,生成一个csv文件返回浏览器,并且是作为附件的形式下载下来. 生成小的csv文件: 生成一个小的csv文件,我们用Python内置的csv模块来处理 ...

  4. 一维跳棋(BFS)

    一维跳棋是一种在1×(2N+1) 的棋盘上玩的游戏.一共有N个棋子,其中N 个是黑的,N 个是白的.游戏开始前,N 个白棋子被放在一头,N 个黑棋子被放在另一头,中间的格子空着. 在这个游戏里有两种移 ...

  5. webview Java与JS互调

    Android调用JS:方法一 webView.loadUrl("javascript:show('"+info+"')"); Android调用JS:方法二 ...

  6. ccf201403-3 记录一个神tmwa了的代码 莫非我没看懂题。。。

    #include <string.h> #include<cstdio> #include<stdio.h> #include <iostream> # ...

  7. 面向对象 part4 构造函数对象重写

    出处 其中深奥之处非看一次能了解 !对象真的有点绕,但是又很严谨

  8. IT人员职业发展规划

  9. 吴裕雄--天生自然 PYTHON3开发学习:XML 解析

    <collection shelf="New Arrivals"> <movie title="Enemy Behind"> <t ...

  10. 在windows系统下安装使用msf

    前沿 msf基本是我在kali里最经使用的工具了 因为今天碰到一些关于VmWare的事情没有解决 windows在前一段时间更新,要求我卸载vmware虚拟机,否则就无法更新. 卸载之后再装回来就无法 ...