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

    文章

    1309

    浏览量

    74940
  • 计算机
    +关注

    关注

    19

    文章

    7835

    浏览量

    93444
  • 服务器
    +关注

    关注

    14

    文章

    10341

    浏览量

    91737

原文标题:GO 中间件 Middleware

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

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

扫码添加小助手

加入工程师交流群

    评论

    相关推荐
    热点推荐

    MIMX9302xxxxD不支持多核中间件吗?

    ) 对于多核中间件,它说: 此可选组件不支持 MIMX9302xxxxD。但是,它确实支持以下评估设备:MCIMX93-EVK,因此可供选择。选中后,相应的支持将添加到配置的包中。 If I select
    发表于 04-09 06:07

    京东缓存中间件架构与缓存内核优化

    一、京东缓存中间件架构 1、背景 在当今高并发、分布式的系统架构中,缓存已成为提升应用性能、降低数据库负载的核心组件。随着业务规模的扩大与系统复杂度的增加,缓存的使用和管理面临诸多挑战:部署模式多样
    的头像 发表于 04-03 16:18 1795次阅读
    京东缓存<b class='flag-5'>中间件</b>架构与缓存内核优化

    谷景DLCHX工字电感在智能插座项目中的应用

    在全球供应链格局深度调整的背景下,电感的国产化替代已成为众多企业提升供应链韧性、控制成本、确保交期的战略选择。近期,谷景成功协助上海某智能设备客户,完成其智能插座项目中关键电感元件的国产化替代,从技术匹配到风险预防,全程护航项目顺利量产。
    的头像 发表于 02-28 09:19 857次阅读

    以“网关中间件”实现充电桩OCPP 1.6安全配置文件无缝升级

    深圳惠志科技有限公司推出的OCPP安全代理网关采用"网关中间件"架构,在充电桩与云端CSMS之间透明地部署,实现充电桩OCPP 1.6协议安全配置文件从Profile 0/1到Profile 2/3的无缝升级,而无需触及桩端硬件与固件。
    的头像 发表于 02-04 11:56 1096次阅读
    以“网关<b class='flag-5'>中间件</b>”实现充电桩OCPP 1.6安全配置文件无缝升级

    博泰车联网携手产业伙伴共建天元OS开源生态

    近日,2025中国汽车软件大会于上海嘉定召开。会上,行业首个覆盖自动驾驶全栈的开源中间件——“天元OS跨域中间件”正式以全栈开源的形式发布。博泰车联作为项目核心共建单位受邀参与,与产业伙伴共同见证并推动中国智能汽车基础软件迈向开
    的头像 发表于 12-31 14:41 581次阅读

    黑芝麻智能携手产业伙伴共建天元OS开源生态

    2025中国汽车软件大会期间,行业首个覆盖自动驾驶全栈的开源中间件——天元OS跨域中间件正式全栈开源发布,黑芝麻智能作为共建单位出席启动仪式。
    的头像 发表于 12-23 11:34 644次阅读

    Neway电机方案在实际应用中效果如何?

    Neway电机方案在实际应用中效果如何?Neway电机方案是深圳市立维创展科技有限公司推出的电机驱动与控制系统解决方案,具有高稳定性、高性价比、小型化等特点,Neway电机方案在实际应用中效果
    发表于 12-03 09:23

    房产数据平台安家go获取地区列表数据的API接口

    如何使用安家go提供的API接口来获取地区列表数据,包括API端点、请求参数、响应格式以及代码实现。我们将逐步引导您完成整个过程,确保您能轻松集成到自己的项目中。 1. API概述 安家go的“获取地区列表”API是一个基于RE
    的头像 发表于 11-21 14:38 464次阅读
    房产数据平台安家<b class='flag-5'>go</b>获取地区列表数据的API接口

    如何选择适合自己项目的通信协议评估工具?

    LZ-DZ200电能质量在线监测装置 选择适合项目的通信协议评估工具,核心是 对齐项目需求与工具能力 ,避免 “过度选型”(用高端工具测简单场景)或 “功能不足”(用轻量工具测复杂协议)。以下是分步
    的头像 发表于 08-27 09:19 920次阅读
    如何选择适合自己<b class='flag-5'>项目的</b>通信协议评估工具?

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

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

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

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

    树莓派项目中10款最佳的DIN导轨外壳!

    ?模块化承包商、电源和灯光控制器都集成在一个紧凑的DIN外壳中。一张图片胜过千言万语。在本文中,我将讨论如何将树莓派安装在DIN导轨上。所有提到的产品都已在各种项目中
    的头像 发表于 06-14 08:34 970次阅读
    树莓派<b class='flag-5'>项目中</b>10款最佳的DIN导轨外壳!

    汽车零部开发项目管理

    汽车零部开发项目管理是一个涉及多环节、多部门协作的复杂过程,需从项目启动到交付全流程进行科学规划与管控。以下从 核心流程 、 关键要素 、 管理工具 及 挑战与应对策略 四方面展开说明: 一、核心
    的头像 发表于 06-09 13:26 1887次阅读

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

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

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

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