0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

Go项目中引入中间件的目的和效果如何

阿铭linux ? 来源:思否开发者社区 ? 作者:guyan0319 ? 2021-08-14 14:24 ? 次阅读
加入交流群
微信小助手二维码

扫码添加小助手

加入工程师交流群

中间件是什么?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

编辑:jq

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • Web
    Web
    +关注

    关注

    2

    文章

    1289

    浏览量

    71631
  • 计算机
    +关注

    关注

    19

    文章

    7679

    浏览量

    91017
  • 服务器
    +关注

    关注

    13

    文章

    9829

    浏览量

    88245

原文标题:GO 中间件 Middleware

文章出处:【微信号:aming_linux,微信公众号:阿铭linux】欢迎添加关注!文章转载请注明出处。

收藏 人收藏
加入交流群
微信小助手二维码

扫码添加小助手

加入工程师交流群

    评论

    相关推荐
    热点推荐

    STM32U575VGT6在cubeMX中没有FATFS中间件,是不支持吗?

    STM32U575VGT6在cubeMX中没有FATFS中间件,是不支持?还是待开发?现在这块板子使用FATFS只能自己手动移植吗?
    发表于 07-30 06:46

    中科创达与ETAS推出预集成多域中间件解决方案

    近日,ETAS 与 ThunderSoft(中科创达)宣布双方建立了紧密合作关系,并将在今年6月24日至25日于路德维希堡举行的汽车电子大会上,联合展示其新开发的、面向高性能计算(HPC)SoC 车载系统的多域预集成中间件解决方案。
    的头像 发表于 06-25 10:16 ?535次阅读

    软件定义汽车时代为什么中间件受青睐

    在“软件定义汽车”时代,随着汽车软件功能渐趋多样化,硬件和软件组件之间的通信和交互开始变得复杂。如今,一辆汽车可能负载百余个电子控制单元(ECU),它们分别控制着包括动力转向、温度控制和安全气囊等在内的多种软件功能。
    的头像 发表于 06-09 11:14 ?453次阅读

    钢厂首选,profinet转profibus在煤电项目中的协议转换解决方案

    钢厂首选,profinet转profibus在煤电项目中的协议转换解决方案
    的头像 发表于 05-06 16:37 ?203次阅读
    钢厂首选,profinet转profibus在煤电<b class='flag-5'>项目中</b>的协议转换解决方案

    智慧路灯的照明效果如何?

    引言 在智慧城市建设的进程中,叁仟智慧路灯已逐渐成为城市道路照明的主力军。其照明效果不仅关系到市民夜间出行的安全与便捷,更对城市的整体形象和生活品质有着深远影响。相较于传统路灯,叁仟智慧路灯借助
    的头像 发表于 03-16 16:10 ?341次阅读

    STM32MP131C CbueMX中间件无RTOS选项是怎么回事?

    如题,STM32MP131C CbueMX中间件无RTOS选项,对比选择STM32MP157芯片是有的,怎么查这部分资料呢
    发表于 03-14 06:59

    2024年AI开发者中间件工具生态全面总结

    进行多方位的总结和梳理。 在第二章《TOP 101-2024 大模型观点》中,生成式 AI 开发者莫尔索总结了 2024 年 AI 开发者中间件工具生态。 ? 全文如下: AI 开发者中间件工具生态
    的头像 发表于 02-14 09:45 ?659次阅读

    安科瑞电力监控系统在浙江某用户侧储能项目的应用

    在保障电力系统正常稳定运行的过程中,引入一套电力监控系统很有必要,本文介绍了安科瑞在浙江某7MW/14MWh用户侧储能项目中提供的整体方案,包括二次分散装置、二次设备预制舱内部分屏柜、调度自动化设备以及一套Acrel-2000电力监控系统。
    的头像 发表于 02-05 13:18 ?485次阅读
    安科瑞电力监控系统在浙江某用户侧储能<b class='flag-5'>项目的</b>应用

    恩智浦强化汽车和工业物联网业务:6.25 亿美元收购中间件企业 TTTech Auto

    恩智浦 NXP 荷兰当地时间本月 7 日宣布已同 TTTech Auto 达成最终协议,计划以 6.25 亿美元(当前约 45.86 亿元人民币)的现金收购这家奥地利汽车中间件企业,强化自身
    的头像 发表于 01-16 11:52 ?1358次阅读
    恩智浦强化汽车和工业物联网业务:6.25 亿美元收购<b class='flag-5'>中间件</b>企业 TTTech Auto

    零念科技PowerD-Sch中间件获ISO 26262 ASIL D级认证

    近日,国际知名的第三方检测认证机构T?V南德意志集团,正式向零念科技颁发的PowerD-Sch确定性调度中间件ISO 26262:2018 ASIL D级功能安全产品认证证书。 这一证书的获得
    的头像 发表于 12-25 15:58 ?590次阅读

    东方通联合openEuler社区即将开启云原生开源中间件 Meetup北京站

    ! openEuler社区云原生开源中间件Meetup北京站将于12月27日举办,由东方通与openEuler社区携手主办。此次交流活动特邀多位业内专家,分享实战案例与前沿技术解析,为技术爱好者、行业从业者、高校学生等加油充电,深化技术交流与学习。同时沙
    的头像 发表于 12-17 14:58 ?777次阅读

    DDS通信中间件——DCPS规范(下)

    DDS通信中间件——DCPS规范(下)本期还是DCPS规范,填上期没有聊完的QoS的坑。本系列文章将包括以下内容陆续更新:1.DDS规范概述2.DCPS规范解读3.DDS-XTypes与IDL解读
    的头像 发表于 11-27 11:47 ?1398次阅读
    DDS通信<b class='flag-5'>中间件</b>——DCPS规范(下)

    中间件全球数据实时同步利器,华为云 EventGrid 事件流重磅发布

    【摘要】 华为云 EventGrid 事件流(简称 EG)作为易用、稳定、高效的数据同步管道连接不同的系统与服务,支持中间件数据在线实时同步。事件流围绕云中间件,降低了中间件之间数据流通的复杂性
    的头像 发表于 10-31 18:39 ?606次阅读
    <b class='flag-5'>中间件</b>全球数据实时同步利器,华为云 EventGrid 事件流重磅发布

    go语言如何解决并发问题

    GO快很多。现在工作中也还是有一些老项目在使用PHP,但21年之后的新项目基本上就都是用GO了。那为什么PHP那么香,还要转战使用GO呢,下
    的头像 发表于 10-23 13:38 ?550次阅读
    <b class='flag-5'>go</b>语言如何解决并发问题

    DDS通信中间件——DCPS规范(上)

    DDS通信中间件——DCPS规范(上)本篇文章继续和大家分享一下对DDS这套规范的理解。预期本系列文章将包括以下内容陆续更新:1.DDS规范概述2.DCPS规范解读3.DDS-XTypes与IDL
    的头像 发表于 09-26 08:08 ?1749次阅读
    DDS通信<b class='flag-5'>中间件</b>——DCPS规范(上)