中间件是什么?go 项目中引入中间件的目的和效果如何?本文详细介绍了golang 中间件。
中间件是一种计算机 软件,可为 操作系统 提供的 软件应用程序 提供服务,以便于各个软件之间的沟通,特别是系统软件和应用软件。广泛用于 web 应用和面向服务的体系结构等。
纵观 go 语言,中间件应用比较普遍,主要应用:
记录对服务器发送的请求(request)
处理服务器响应(response )
请求和处理之间做一个权限认证工作
远程调用
安全
等等
中间件处理程序是简单的http.handler,它包装另一个http.handler做请求的一些预处理和/或后处理。它被称为“中间件”,因为它位于 go web 服务器和实际处理程序之间的中间位置。
下面是一些中间件例子
记录日志中间件
package main
import (
“fmt”
“log”
“net/http”
)
func logging(f http.handlerfunc) http.handlerfunc {
return func(w http.responsewriter, r *http.request) {
log.println(r.url.path)
f(w, r)
}
}
func foo(w http.responsewriter, r *http.request) {
fmt.fprintln(w, “foo”)
}
func bar(w http.responsewriter, r *http.request) {
fmt.fprintln(w, “bar”)
}
func main() {
http.handlefunc(“/foo”, logging(foo))
http.handlefunc(“/bar”, logging(bar))
http.listenandserve(“:8080”, nil)
}
访问 http://localhost:8080/foo
返回结果
foo
将上面示例修改下,也可以实现相同的功能。
package main
import (
“fmt”
“log”
“net/http”
)
func foo(w http.responsewriter, r *http.request) {
fmt.fprintln(w, “foo”)
}
func bar(w http.responsewriter, r *http.request) {
fmt.fprintln(w, “bar”)
}
func loggingmiddleware(next http.handler) http.handler {
return http.handlerfunc(func(w http.responsewriter, r *http.request) {
log.println(r.url.path)
next.servehttp(w, r)
})
}
func main() {
http.handle(“/foo”, loggingmiddleware(http.handlerfunc(foo)))
http.handle(“/bar”, loggingmiddleware(http.handlerfunc(bar)))
http.listenandserve(“:8080”, nil)
}
访问 http://localhost:8080/foo
返回结果
foo
多中间件例子
package main
import (
“fmt”
“log”
“net/http”
“time”
)
type middleware func(http.handlerfunc) http.handlerfunc// logging logs all requests with its path and the time it took to processfunc logging() middleware {
// create a new middleware
return func(f http.handlerfunc) http.handlerfunc {
// define the http.handlerfunc
return func(w http.responsewriter, r *http.request) {
// do middleware things
start := time.now()
defer func() { log.println(r.url.path, time.since(start)) }()
// call the next middleware/handler in chain
f(w, r)
}
}
}
// method ensures that url can only be requested with a specific method, else returns a 400 bad requestfunc method(m string) middleware {
// create a new middleware
return func(f http.handlerfunc) http.handlerfunc {
// define the http.handlerfunc
return func(w http.responsewriter, r *http.request) {
// do middleware things
if r.method != m {
http.error(w, http.statustext(http.statusbadrequest), http.statusbadrequest)
return
}
// call the next middleware/handler in chain
f(w, r)
}
}
}
// chain applies middlewares to a http.handlerfuncfunc chain(f http.handlerfunc, middlewares 。。.middleware) http.handlerfunc {
for _, m := range middlewares {
f = m(f)
}
return f
}
func hello(w http.responsewriter, r *http.request) {
fmt.fprintln(w, “hello world”)
}
func main() {
http.handlefunc(“/”, chain(hello, method(“get”), logging()))
http.listenandserve(“:8080”, nil)
}
中间件本身只是将其http.handlerfunc作为其参数之一,包装它并返回一个新http.handlerfunc的服务器来调用。在这里,我们定义了一种新类型middleware,最终可以更容易地将多个中间件链接在一起。
当然我们也可以改成如下形式
package main
import (
“fmt”
“log”
“net/http”
“time”
)
type middleware func(http.handler) http.handlerfunc hello(w http.responsewriter, r *http.request) {
fmt.fprintln(w, “hello world”)
}
func chain(f http.handler, mmap 。。.middleware) http.handler {
for _, m := range mmap {
f = m(f)
}
return f
}
func method(m string) middleware {
return func(f http.handler) http.handler {
return http.handlerfunc(func(w http.responsewriter, r *http.request) {
log.println(r.url.path)
if r.method != m {
http.error(w, http.statustext(http.statusbadrequest), http.statusbadrequest)
return
}
f.servehttp(w, r)
})
}
}
func logging() middleware {
return func(f http.handler) http.handler {
return http.handlerfunc(func(w http.responsewriter, r *http.request) {
//log.println(r.url.path)
// do middleware things
start := time.now()
defer func() { log.println(r.url.path, time.since(start)) }()
f.servehttp(w, r)
})
}
}
func main() {
http.handle(“/”, chain(http.handlerfunc(hello), method(“get”), logging()))
http.listenandserve(“:8080”, nil)
}
在 gin 框架下实现中间件
r := gin.default() 创建带有默认中间件的路由,默认是包含 logger 和 recovery 中间件的
r :=gin.new() 创建带有没有中间件的路由
示例
package main
import (
“github.com/gin-gonic/gin”
“log”
“time”
)
func logger() gin.handlerfunc {
return func(c *gin.context) {
t := time.now()
// set example variable
c.set(“example”, “12345”)
// before request
c.next()
// after request
latency := time.since(t)
log.print(latency) //时间 0s
// access the status we are sending
status := c.writer.status()
log.println(status) //状态 200
}
}
func main() {
r := gin.new()
r.use(logger())
r.get(“/test”, func(c *gin.context) {
example := c.mustget(“example”)。(string)
// it would print: “12345”
log.println(example)
})
// listen and serve on 0.0.0.0:8080
r.run(“:8080”)
}
以上示例也可改为
package main
import (
“github.com/gin-gonic/gin”
“log”
“time”
)
func logger() gin.handlerfunc {
return func(c *gin.context) {
t := time.now()
// set example variable
c.set(“example”, “12345”)
// before request
c.next()
// after request
latency := time.since(t)
log.print(latency) //时间 0s
// access the status we are sending
status := c.writer.status()
log.println(status) //状态 200
}
}
func main() {
r := gin.new()
r.get(“/test”, logger(), func(c *gin.context) {
example := c.mustget(“example”)。(string)
// it would print: “12345”
log.println(example)
})
// listen and serve on 0.0.0.0:8080
r.run(“:8080”)
}
即不用 r.use 添加中间件,直接将 logger() 写到 r.get 方法的参数里(“/test”之后)。
更多 gin 中间件示例可参考 https://github.com/gin-gonic/gin
转自:guyan0319
segmentfault.com/a/1190000018819804
多彩的移动型机器人,让人们不再感到孤单
搞事情了搞事情了!八月支付宝、微信联手正式开启无现金周
福特与3M展开合作 将在本周开始生产呼吸机
佳能eosm6和索尼a6300哪个好 随身微单谁更出彩
2010 ADI 中国大学创新设计竞赛于武汉成功落下帷幕
Go项目中引入中间件的目的和效果如何
IC代工业:强者恒强弱者出局
多项利好因素全面推进智能家居行业发展,家用安防领域前景被看好
隔离变压器在UPS中的设置
汽车消费政策为车市注入强心剂,中国汽车销量5月有望继续上升
联芯三大亮点闪耀MAE,推动3G/4G科技平民化
智能调度管理系统
政策助推,2017上半年中国AI投资总额达635亿元
需要了解Embeded linux的地址映射
PCI Express通过结合Nexus FPGA 技术平台与 LUT 实现以太网协议
中国联通正在携手华为打造基于5G网络建设的全场景综合解决方案
ACPL-M43U/M61U/M46U安华高工业应用
升级到iOS14后如何小窗口化
农药检测仪的工作原理及性能介绍
AI医疗才起步 AI在医疗领域作为帮手的角色会越来越重要