15分钟学 Go 第 41 天:中间件的使用
第41天:中间件的使用
目标:学习如何在Go语言的Web服务中使用中间件
中间件(Middleware)是Web开发中的一种常见设计模式,通常用于处理请求和响应过程中的一些共通功能。比如:日志记录、认证授权、请求处理、响应修改等。在Go语言的Web开发中,中间件是通过装饰器模式实现的,可以帮助我们在请求处理流程中插入额外的操作。
本节内容将带领你详细学习Go语言中如何使用中间件,尤其是在Web服务中。我们会通过以下几个方面来阐述这一主题:
- 中间件的定义和用途
- Go语言中间件的实现
- Go标准库
net/http
中的中间件实现 - 基于
gorilla/mux
的中间件实现 - 常见中间件案例:日志记录、身份验证、跨域处理
- 中间件执行流程图
1. 中间件的定义和用途
在Web应用程序中,中间件通常是指位于客户端请求和服务器响应之间的一个或多个处理组件。这些组件可以:
- 修改请求:比如添加请求头、解析请求体等。
- 控制请求流:比如进行身份验证,检查用户是否有权限访问某些资源。
- 记录日志:记录访问日志、错误日志等。
- 修改响应:如修改返回的内容、设置响应头等。
中间件的特点是,它是独立的功能单元,能够插入到请求处理链的任意位置,并且每个中间件组件只负责某一特定功能。
2. Go语言中间件的实现
在Go语言中,中间件通常是一个函数,它接收一个http.Handler
接口类型的参数,返回一个新的http.Handler
,通常在返回的新http.Handler
中会对请求或响应进行处理。
Go中间件的一般签名如下:
type Middleware func(http.Handler) http.Handler
其中,http.Handler
是Go语言标准库中定义的接口类型,用于处理HTTP请求。中间件的作用是将请求传递到下一个处理器。
3. Go标准库net/http
中的中间件实现
Go标准库中的net/http
包是处理HTTP请求和响应的核心。我们可以通过定义一个函数来实现中间件。
下面是一个简单的示例,展示了如何在Go语言中使用中间件进行日志记录:
示例代码:简单的日志记录中间件
package mainimport ("fmt""log""net/http""time"
)// 定义中间件类型
type Middleware func(http.Handler) http.Handler// 日志记录中间件
func LoggingMiddleware(next http.Handler) http.Handler {return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {start := time.Now()log.Printf("Started %s %s", r.Method, r.URL.Path)next.ServeHTTP(w, r)log.Printf("Completed in %v", time.Since(start))})
}// 处理请求的实际处理器
func HelloHandler(w http.ResponseWriter, r *http.Request) {fmt.Fprintln(w, "Hello, World!")
}func main() {// 创建一个路由器mux := http.NewServeMux()// 将处理器注册到路由器mux.HandleFunc("/", HelloHandler)// 包裹中间件handler := LoggingMiddleware(mux)// 启动HTTP服务器log.Fatal(http.ListenAndServe(":8080", handler))
}
代码解析
LoggingMiddleware
是我们定义的日志中间件,它接收一个http.Handler
,并返回一个新的http.Handler
。HelloHandler
是一个简单的请求处理函数,当访问根路径时返回“Hello, World!”。LoggingMiddleware
会在请求开始时记录请求的路径和方法,然后调用next.ServeHTTP(w, r)
来将请求传递给下一个处理器,最后记录请求的处理时间。
运行该代码后,在终端你会看到类似以下的日志:
Started GET /
Completed in 500ns
4. 基于gorilla/mux
的中间件实现
gorilla/mux
是一个非常流行的Go语言路由器,它支持中间件的功能,能够让我们更方便地组织和使用中间件。
下面是一个使用gorilla/mux
的中间件示例:
示例代码:基于gorilla/mux
的中间件实现
package mainimport ("fmt""log""net/http""time""github.com/gorilla/mux"
)// 日志记录中间件
func LoggingMiddleware(next http.Handler) http.Handler {return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {start := time.Now()log.Printf("Started %s %s", r.Method, r.URL.Path)next.ServeHTTP(w, r)log.Printf("Completed in %v", time.Since(start))})
}// 处理请求的实际处理器
func HelloHandler(w http.ResponseWriter, r *http.Request) {fmt.Fprintln(w, "Hello, Gorilla Mux!")
}func main() {// 创建一个mux路由r := mux.NewRouter()// 将处理器注册到路由器r.HandleFunc("/", HelloHandler).Methods("GET")// 包裹中间件r.Use(LoggingMiddleware)// 启动HTTP服务器log.Fatal(http.ListenAndServe(":8080", r))
}
代码解析
- 我们通过
mux.NewRouter()
创建了一个新的路由器。 - 使用
r.Use(LoggingMiddleware)
将日志记录中间件应用到整个路由器。 - 在请求被处理前和处理后,都会通过
LoggingMiddleware
记录日志信息。
运行该代码,访问http://localhost:8080/
,你会看到与上一个示例类似的日志输出。
5. 常见中间件案例
除了日志记录中间件,Web开发中还有一些其他常见的中间件,我们将在此列举并展示如何在Go中实现。
1. 认证和授权中间件
认证中间件用于验证用户是否已登录或是否拥有访问某些资源的权限。下面是一个简单的身份验证中间件:
func AuthMiddleware(next http.Handler) http.Handler {return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {authHeader := r.Header.Get("Authorization")if authHeader == "" {http.Error(w, "Forbidden", http.StatusForbidden)return}// 假设我们只是简单地检查一个固定的tokenif authHeader != "Bearer secret-token" {http.Error(w, "Forbidden", http.StatusForbidden)return}next.ServeHTTP(w, r)})
}
2. 跨域资源共享(CORS)中间件
CORS中间件用于处理跨域请求,它通常会添加Access-Control-Allow-Origin
等头信息,允许来自其他域的请求。
func CORSMiddleware(next http.Handler) http.Handler {return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {w.Header().Set("Access-Control-Allow-Origin", "*")w.Header().Set("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE")w.Header().Set("Access-Control-Allow-Headers", "Content-Type")next.ServeHTTP(w, r)})
}
3. 请求限流中间件
请求限流中间件用于限制客户端的请求频率,防止服务器过载。可以根据具体需求实现如IP限流、用户限流等策略。
6. 中间件执行流程图
我们通过以下的流程图来帮助理解Go Web服务中中间件的执行顺序:
┌────────────────────────┐
│ 请求到达 │
└────────────────────────┘│▼┌─────────────────────┐│ 进入第一个中间件 │└─────────────────────┘│▼┌─────────────────────┐│ 第一个中间件处理 │└─────────────────────┘│▼┌───────────────────┐│ 进入第二个中间件 │└───────────────────┘│▼┌───────────────────┐│ 第二个中间件处理 │└───────────────────┘│▼┌────────────────┐│ 请求到达处理器 │└────────────────┘│▼┌────────────────┐│ 返回响应 │└────────────────┘│▼┌───────────────────┐│ 进入响应中间件 │└───────────────────┘│▼┌───────────────────┐│ 响应中间件处理 │└───────────────────┘│▼┌────────────────┐│ 响应发送给客户端 │└────────────────┘
总结
中间件是Go语言Web开发中非常重要的组成部分,能够帮助我们处理请求、响应,增加一些通用的功能。在本节中,我们深入探讨了Go语言如何实现中间件,涵盖了日志记录、中间件链、认证授权等实际应用。希望你能通过这些示例理解中间件的工作原理,并能够在自己的Web项目中灵活使用。
怎么样今天的内容还满意吗?再次感谢观众老爷的观看,关注GZH:凡人的AI工具箱,回复666,送您价值199的AI大礼包。最后,祝您早日实现财务自由,还请给个赞,谢谢!
相关文章:
15分钟学 Go 第 41 天:中间件的使用
第41天:中间件的使用 目标:学习如何在Go语言的Web服务中使用中间件 中间件(Middleware)是Web开发中的一种常见设计模式,通常用于处理请求和响应过程中的一些共通功能。比如:日志记录、认证授权、请求处理…...
《Python 与 SQLite:强大的数据库组合》
《Python 与 SQLite:强大的数据库组合》 一、Python 与 SQLite 的结合二、安装与连接(一)安装 SQLite 模块(二)连接到数据库 三、数据库操作(一)创建表格(二)插入数据&am…...

Golang | Leetcode Golang题解之第552题学生出勤记录II
题目: 题解: const mod int 1e9 7type matrix [6][6]intfunc (a matrix) mul(b matrix) matrix {c : matrix{}for i, row : range a {for j : range b[0] {for k, v : range row {c[i][j] (c[i][j] v*b[k][j]) % mod}}}return c }func (a matrix) p…...

Vue3 常用代码指南手抄,超详细 cheatsheet
一、Vue3 基础 1.1 创建 Vue3 项目 使用 Vite 创建 npm create vitelatest my-vue-app -- --template vue cd my-vue-app npm install npm run dev使用 Vue CLI 创建 npm install -g vue/cli vue create my-vue-app1.2 项目结构 my-vue-app ├── node_modules ├── pu…...
结构体是否包含特定类型的成员变量
结构体是否包含特定类型的成员变量 在C中,可以使用模板元编程和类型特性(type traits)来判断一个结构体是否包含特定类型的成员变量。这通常通过std::is_member_object_pointer类型特性来实现,它可以用来检查给定的成员指针是否指…...

堆排序与链式二叉树:数据结构与排序算法的双重探索
大家好,我是小卡皮巴拉 文章目录 目录 引言 一.堆排序 1.1 版本一 核心概念 堆排序过程 1.2 版本二 堆排序函数 HeapSort 向下调整算法 AdjustDown 向上调整算法 AdjustUp 二.链式二叉树 2.1 前中后序遍历 链式二叉树的结构 创建链式二叉树 前序遍历…...

用 Python 从零开始创建神经网络(四):激活函数(Activation Functions)
激活函数(Activation Functions) 引言1. 激活函数的种类a. 阶跃激活功能b. 线性激活函数c. Sigmoid激活函数d. ReLU 激活函数e. more 2. 为什么使用激活函数3. 隐藏层的线性激活4. 一对神经元的 ReLU 激活5. 在隐蔽层中激活 ReLU6. ReLU 激活函数代码7. …...

使用 Flask 和 ONLYOFFICE 实现文档在线编辑功能
提示:CSDN 博主测评ONLYOFFICE 文章目录 引言技术栈环境准备安装 ONLYOFFICE 文档服务器获取 API 密钥安装 Flask 和 Requests 创建 Flask 应用项目结构编写 app.py创建模板 templates/index.html 运行应用功能详解文档上传生成编辑器 URL显示编辑器回调处理 安全性…...
【C++】【算法基础】序列编辑距离
编辑距离 题目 给定 n n n个长度不超过 10 10 10 的字符串以及 m m m 次询问,每次询问给出一个字符串和一个操作次数上限。 对于每次询问,请你求出给定的 n n n个字符串中有多少个字符串可以在上限操作次数内经过操作变成询问给出的字符串。 每个…...

【Android】轮播图——Banner
引言 Banner轮播图是一种在网页和移动应用界面设计中常见的元素,主要用于在一个固定的区域内自动或手动切换一系列图片,以展示不同的内容或信息。这个控件在软件当中经常看到,商品促销、热门歌单、头像新闻等等。它不同于ViewPgaer在于无需手…...

学SQL,要安装什么软件?
先上结论,推荐MySQLDbeaver的组合。 学SQL需要安装软件吗? 记得几年前我学习SQL的时候,以为像Java、Python一样需要安装SQL软件包,后来知道并没有所谓SQL软件,因为SQL是一种查询语言,它用来对数据库进行操…...
webstorm 设置总结
编辑器-》文件类型-》忽略的文件和文件夹-》加上node_modules 修改WebStorm 内存有两种方式。 1. 点击菜单中的Help -> change memory settings 弹出设置内存窗口,修改最大内存大小。然后点击Save and Restart 即可。 2. 点击菜单中的Help -> Edit Custom V…...

基于Spring Boot的养老保险管理系统的设计与实现,LW+源码+讲解
摘 要 如今社会上各行各业,都喜欢用自己行业的专属软件工作,互联网发展到这个时候,人们已经发现离不开了互联网。新技术的产生,往往能解决一些老技术的弊端问题。因为传统养老保险管理系统信息管理难度大,容错率低&a…...

Java | Leetcode Java题解之第541题反转字符串II
题目: 题解: class Solution {public String reverseStr(String s, int k) {int n s.length();char[] arr s.toCharArray();for (int i 0; i < n; i 2 * k) {reverse(arr, i, Math.min(i k, n) - 1);}return new String(arr);}public void reve…...
sql分区
将学员表student按所在城市使用PARTITION BY LIST 1、创建分区表。 CREATE TABLE public.student( sno numeric(4,0), sname character varying(20 char),gender character varying(2 char), phone numeric(11,0), …...

[OpenGL]使用OpenGL实现硬阴影效果
一、简介 本文介绍了如何使用OpenGL实现硬阴影效果,并在最后给出了全部的代码。本文基于[OpenGL]渲染Shadow Map,实现硬阴影的流程如下: 首先,以光源为视角,渲染场景的深度图,将light space中的深度图存储…...

嵌入式采集网关(golang版本)
为了一次编写到处运行,使用纯GO编写,排除CGO,解决在嵌入式中交叉编译难问题 硬件设备:移远EC200A-CN LTE Cat 4 无线通信模块,搭载openwrt操作系统,90M内存...

ctfshow(328)--XSS漏洞--存储型XSS
Web328 简单阅读一下页面。 是一个登录系统,存在一个用户管理数据库。 那么我们注册一个账号,在账号或者密码中植入HTML恶意代码,当管理员访问用户管理数据库页面时,就会触发我们的恶意代码。 思路 我们向数据库中写入盗取管理员…...
【C#】Thread.CurrentThread的用法
Thread.CurrentThread 是 System.Threading.Thread 类的一个静态属性,它返回当前正在执行的线程对象。通过 Thread.CurrentThread,可以访问和修改当前线程的各种属性和方法。 下面是一些常见的用法和示例: 1. 获取当前线程的信息 使用 Thr…...

简单分享一下淘宝商品数据自动化抓取的技术实现与挑战
在电子商务领域,数据是驱动决策的关键。淘宝作为国内最大的电商平台之一,其商品数据对电商从业者来说具有极高的价值。然而,从淘宝平台自动化抓取商品数据并非易事,涉及多重技术和法律挑战。本文将从技术层面分析实现淘宝商品数据…...
Android Wi-Fi 连接失败日志分析
1. Android wifi 关键日志总结 (1) Wi-Fi 断开 (CTRL-EVENT-DISCONNECTED reason3) 日志相关部分: 06-05 10:48:40.987 943 943 I wpa_supplicant: wlan0: CTRL-EVENT-DISCONNECTED bssid44:9b:c1:57:a8:90 reason3 locally_generated1解析: CTR…...
论文解读:交大港大上海AI Lab开源论文 | 宇树机器人多姿态起立控制强化学习框架(二)
HoST框架核心实现方法详解 - 论文深度解读(第二部分) 《Learning Humanoid Standing-up Control across Diverse Postures》 系列文章: 论文深度解读 + 算法与代码分析(二) 作者机构: 上海AI Lab, 上海交通大学, 香港大学, 浙江大学, 香港中文大学 论文主题: 人形机器人…...

盘古信息PCB行业解决方案:以全域场景重构,激活智造新未来
一、破局:PCB行业的时代之问 在数字经济蓬勃发展的浪潮中,PCB(印制电路板)作为 “电子产品之母”,其重要性愈发凸显。随着 5G、人工智能等新兴技术的加速渗透,PCB行业面临着前所未有的挑战与机遇。产品迭代…...
【磁盘】每天掌握一个Linux命令 - iostat
目录 【磁盘】每天掌握一个Linux命令 - iostat工具概述安装方式核心功能基础用法进阶操作实战案例面试题场景生产场景 注意事项 【磁盘】每天掌握一个Linux命令 - iostat 工具概述 iostat(I/O Statistics)是Linux系统下用于监视系统输入输出设备和CPU使…...
C# SqlSugar:依赖注入与仓储模式实践
C# SqlSugar:依赖注入与仓储模式实践 在 C# 的应用开发中,数据库操作是必不可少的环节。为了让数据访问层更加简洁、高效且易于维护,许多开发者会选择成熟的 ORM(对象关系映射)框架,SqlSugar 就是其中备受…...

用docker来安装部署freeswitch记录
今天刚才测试一个callcenter的项目,所以尝试安装freeswitch 1、使用轩辕镜像 - 中国开发者首选的专业 Docker 镜像加速服务平台 编辑下面/etc/docker/daemon.json文件为 {"registry-mirrors": ["https://docker.xuanyuan.me"] }同时可以进入轩…...
Caliper 配置文件解析:config.yaml
Caliper 是一个区块链性能基准测试工具,用于评估不同区块链平台的性能。下面我将详细解释你提供的 fisco-bcos.json 文件结构,并说明它与 config.yaml 文件的关系。 fisco-bcos.json 文件解析 这个文件是针对 FISCO-BCOS 区块链网络的 Caliper 配置文件,主要包含以下几个部…...
Device Mapper 机制
Device Mapper 机制详解 Device Mapper(简称 DM)是 Linux 内核中的一套通用块设备映射框架,为 LVM、加密磁盘、RAID 等提供底层支持。本文将详细介绍 Device Mapper 的原理、实现、内核配置、常用工具、操作测试流程,并配以详细的…...
C++.OpenGL (14/64)多光源(Multiple Lights)
多光源(Multiple Lights) 多光源渲染技术概览 #mermaid-svg-3L5e5gGn76TNh7Lq {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-3L5e5gGn76TNh7Lq .error-icon{fill:#552222;}#mermaid-svg-3L5e5gGn76TNh7Lq .erro…...
Mysql8 忘记密码重置,以及问题解决
1.使用免密登录 找到配置MySQL文件,我的文件路径是/etc/mysql/my.cnf,有的人的是/etc/mysql/mysql.cnf 在里最后加入 skip-grant-tables重启MySQL服务 service mysql restartShutting down MySQL… SUCCESS! Starting MySQL… SUCCESS! 重启成功 2.登…...