(Go Gin)Gin学习笔记(四)Gin的数据渲染和中间件的使用:数据渲染、返回JSON、浅.JSON()源码、中间件、Next()方法

1. 数据渲染

1.1 各种数据格式的响应

  • json、结构体、XML、YAML类似于java的properties、ProtoBuf

1.1.1 返回JSON

package mainimport ("github.com/gin-gonic/gin""net/http"
)func main() {r := gin.Default()r.POST("/demo", func(res *gin.Context) {res.JSON(http.StatusOK, gin.H{"message": "success",})})r.Run(":8080")
}

1.1.2 返回结构体

r.GET("/demo", func(res *gin.Context) {var obj struct {name stringage  int8}obj.age = 1obj.name = "张三"res.JSON(http.StatusOK, obj)
})

1.1.3 XML 和 YAML

// 3.XML
r.GET("/someXML", func(c *gin.Context) {c.XML(200, gin.H{"message": "abc"})
})
// 4.YAML响应
r.GET("/someYAML", func(c *gin.Context) {c.YAML(200, gin.H{"name": "zhangsan"})
})

1.1.4 浅浅扒一下源码

进入res.JSON函数里面看一下

res.JSON(http.StatusOK, obj)
func (c *Context) JSON(code int, obj any) {c.Render(code, render.JSON{Data: obj})
}
  • (c *Context) 代表可以被Context类型调用
  • (code int, obj any) 传入参数,状态码和返回对象

它本身内部再次封装了一层提供给Render类型

func (c *Context) Render(code int, r render.Render) {c.Status(code)if !bodyAllowedForStatus(code) {r.WriteContentType(c.Writer)c.Writer.WriteHeaderNow()return}if err := r.Render(c.Writer); err != nil {// Pushing error to c.Errors_ = c.Error(err)c.Abort()}
}

进入Render里面,可以看到

  • (code int, r render.Render) 参数进行了更改,传入了render包下的Render类型

可以看一下Render这个接口

type Render interface {// Render writes data with custom ContentType.Render(http.ResponseWriter) error// WriteContentType writes custom ContentType.WriteContentType(w http.ResponseWriter)
}

接口还提供了一个可以修改ContentType的方法

if !bodyAllowedForStatus(code) {r.WriteContentType(c.Writer)c.Writer.WriteHeaderNow()return
}
  • bodyAllowedForStatus()进行了判断
func bodyAllowedForStatus(status int) bool {switch {case status >= 100 && status <= 199:return falsecase status == http.StatusNoContent:return falsecase status == http.StatusNotModified:return false}return true
}

判断了传入的状态码是否符合正确的状态码,并返回

  • 当bodyAllowedForStatus()判断为错误状态码时

    会在返回对象中写入ContentType内容

​ c.Writer.WriteHeaderNow()还会写入文本流中

再看一下其他返回的类型;例如XML

func (c *Context) XML(code int, obj any) {c.Render(code, render.XML{Data: obj})
}

在内部封装时,只是标注了不同的render类型

1.2 重定向

访问/demo地址时,将页面重定向跳转至其他页面

package mainimport ("github.com/gin-gonic/gin""net/http"
)func main() {r := gin.Default()r.GET("/demo", func(c *gin.Context) {c.Redirect(http.StatusMovedPermanently, "http://www.baidu.com")})r.Run(":8080")
}

2. 中间件

2.1 全局中间件

  • 所有请求都经过此中间件
package mainimport ("github.com/gin-gonic/gin""log""time"
)func MiddleWare() gin.HandlerFunc {return func(c *gin.Context) {t := time.Now()log.Println("中间件开始运行:", t)c.Set("middle_1", "中间件1执行结束")status := c.Writer.Status()log.Println("中间件执行结束:", status)t2 := time.Since(t)log.Println("耗时:", t2)}
}func main() {r := gin.Default()// 注册中间件r.Use(MiddleWare())r.GET("/demo", func(c *gin.Context) {// 获得内容m, _ := c.Get("middle_1")log.Println("中间件接收参数:", m)c.JSON(200, gin.H{"中间件接收参数:": m})})r.Run(":8080")
}

测试:http://localhost:8080/demo

返回结果:

[GIN-debug] Listening and serving HTTP on :8080
2025/04/29 00:12:34 中间件开始运行: 2025-04-29 00:12:34.5992889 +0800 CST m=+1.770059901
2025/04/29 00:12:34 中间件执行结束: 200
2025/04/29 00:12:34 耗时: 11.5258ms
2025/04/29 00:12:34 中间件接收参数: 中间件1执行结束
[GIN] 2025/04/29 - 00:12:34 | 200 |     11.5258ms |             ::1 | GET      "/demo"

gin 使用r.Use()来注册一个组件

  • 在注册组件时,我们需要规定函数的返回类型,这才能让gin知道这是什么组件
func MiddleWare() gin.HandlerFunc {return func(c *gin.Context) {t := time.Now()log.Println("中间件开始运行:", t)c.Set("middle_1", "中间件1执行结束")status := c.Writer.Status()log.Println("中间件执行结束:", status)t2 := time.Since(t)log.Println("耗时:", t2)}
}
  • 这里MiddleWare()函数规定了返回类型是 gin.HandlerFunc ,这就代表这个函数是一个处理类

2.1.1 Next() 方法

我们在正常注册中间件时,会打断原有的运行流程,但是你可以在中间件函数内部添加Next()方法,这样可以让原有的运行流程继续执行,当原有的运行流程结束后再回来执行中间件内部的内容

package mainimport ("github.com/gin-gonic/gin""log""time"
)func MiddleWare() gin.HandlerFunc {return func(c *gin.Context) {t := time.Now()log.Println("中间件开始运行:", t)// 开启正常执行流程c.Next()c.Set("middle_1", "中间件1执行结束")status := c.Writer.Status()log.Println("中间件执行结束:", status)t2 := time.Since(t)log.Println("耗时:", t2)}
}func main() {r := gin.Default()// 注册中间件r.Use(MiddleWare())r.GET("/demo", func(c *gin.Context) {// 获得内容m, _ := c.Get("middle_1")log.Println("中间件接收参数:", m)c.JSON(200, gin.H{"中间件接收参数:": m})})r.Run(":8080")
}

测试:http://localhost:8080/demo

返回结果:

[GIN-debug] Listening and serving HTTP on :8080
2025/04/29 00:14:14 中间件开始运行: 2025-04-29 00:14:14.5697461 +0800 CST m=+2.981609901
2025/04/29 00:14:14 中间件接收参数: <nil>
2025/04/29 00:14:14 中间件执行结束: 200
2025/04/29 00:14:14 耗时: 14.0262ms
[GIN] 2025/04/29 - 00:14:14 | 200 |     14.0262ms |             ::1 | GET      "/demo"

可以看到使用next后,正常执行流程中并没有获得到中间件设置的值

2.2 局部中间件

package mainimport ("github.com/gin-gonic/gin""log""time"
)func MiddleWare() gin.HandlerFunc {return func(c *gin.Context) {t := time.Now()log.Println("中间件开始运行:", t)c.Set("middle_1", "中间件1执行结束")status := c.Writer.Status()log.Println("中间件执行结束:", status)t2 := time.Since(t)log.Println("耗时:", t2)}
}func main() {r := gin.Default()// 局部中间件-在为一个请求添加执行函数时即可挂载中间件r.GET("/demo", MiddleWare(), func(c *gin.Context) {// 获得内容m, _ := c.Get("middle_1")log.Println("中间件接收参数:", m)c.JSON(200, gin.H{"中间件接收参数:": m})})r.Run(":8080")
}
  • 为你想给哪一个请求挂载中间件,直接在对应的请求中添加中间件函数即可

3. ❤️GoGin框架——前文链接

Gin框架学习参考网站:gin框架·Go语言中文文档

  • (Go Gin)基于Go的WEB开发框架,GO Gin是什么?怎么启动?本文给你答案
  • (Go Gin)Gin学习笔记(二):路由配置、基本路由、表单参数、上传单个文件、上传多个文件、浅扒路由原理

    (Go Gin)Gin学习笔记(三):数据解析和绑定,结构体分析,包括JSON解析、form解析、URL解析,区分绑定的Bind方法

4. 💕👉博客专栏

  • Golang专栏-包含基础、Gin、Goam等知识
  • 云原生专栏-包含k8s、docker等知识
  • 从0开始学习云计算-华为HCIP证书
  • JUC专栏-带你快速领悟JUC的知识!
  • JVM专栏-深入Java虚拟机,理解JVM的原理
  • 基于Java研究 数据结构与算法-包含贪心算法、加权图、最短路径算法等知识
  • Docker专栏-上手热门容器技术Docker
  • SpringBoot专栏-学习SpringBoot快速开发后端
  • 项目管理工具的学习-设计技术:Maven、Git、Gradle等相关管理工具
  • JavaSE-全面了解Java基础
  • JS专栏-使用JS作的一部分实例~
  • 使用CSS所作的一部分案例

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/pingmian/78959.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

实验:串口通信

/************************************************* * AT89C52 串口通信实验&#xff08;实用修正版&#xff09; * 特点&#xff1a; * 1. 解决所有编译警告 * 2. 保持代码简洁 * 3. 完全功能正常 ************************************************/ #include <re…

智驾赛道的诺曼底登陆,Momenta上海车展雄起

作者 |芦苇 编辑 |德新 今年的上海车展依旧热闹非凡&#xff0c;但火热的车市背后也是暗流涌动。尤其对智驾供应商而言&#xff0c;「智驾平权」带动了解决方案大量上车&#xff0c;各大主机厂纷纷选定各自的主要供应商&#xff0c;这也意味着赛道机会越发收敛。 正如汽车品牌…

Java 事务详解

目录 一、事务的基本概念1.1 什么是事务?1.2 事务的 ACID 特性二、Java 事务管理的实现方式2.1 JDBC 事务管理2.2 Spring 事务管理2.2.1 添加 Spring 依赖2.2.2 配置 Spring 事务管理2.2.3 使用 Spring 事务注解三、事务隔离级别四、最佳实践4.1 尽量缩小事务范围4.2 合理选择…

DirectX12(D3D12)基础教程七 深度模板视图\剔除\谓词

本章主要讲遮挡&#xff0c;作者认为比较复杂有难度的知识点&#xff0c;作为基础教程不会深入讲解。 GPU渲染管线 主要包括以下阶段 输入装配&#xff08;IA&#xff09;&#xff1a;读取顶点数据 &#xff0c;定义顶点数据结构顶点着色&#xff08;VS&#xff09;&#xf…

温补晶振(TCXO)稳定性优化:从实验室到量产的关键技术

在现代通信、航空航天、5G基站等对频率稳定性要求极高的领域&#xff0c;温补晶振&#xff08;TCXO&#xff09;扮演着不可或缺的角色。其稳定性直接影响系统的性能与可靠性&#xff0c;因此&#xff0c;对TCXO稳定性优化技术的研究与实践至关重要。 一、温度补偿算法&#xff…

C++,设计模式,【建造者模式】

文章目录 通俗易懂的建造者模式&#xff1a;手把手教你造电脑一、现实中的建造者困境二、建造者模式核心思想三、代码实战&#xff1a;组装电脑1. 产品类 - 电脑2. 抽象建造者 - 装机师傅3. 具体建造者 - 电竞主机版4. 具体建造者 - 办公主机版5. 指挥官 - 装机总控6. 客户端使…

前端基础之《Vue(13)—重要API》

重要的API 一、nextTick() 1、写法 Vue.$nextTick()或者this.$nextTick() 原因&#xff1a; set操作代码是同步的&#xff0c;但是代码背后的行为是异步的。set操作修改声明式变量&#xff0c;触发re-render生成新的虚拟DOM&#xff0c;进一步执行diff运算&#xff0c;找到…

Windows 中搭建 browser-use WebUI 1.4

目录 1. 背景介绍2. 搭建过程3. 补充 1. 背景介绍 背景&#xff1a;想要在 Windows 中复现 browser-use WebUI pickle反序列化漏洞&#xff0c;该漏洞在 v1.7 版本中已经修复&#xff0c;所以需要搭建 小于 1.7 版本的环境&#xff0c;我这里搭建的是 1.4 版本。 项目地址&am…

【数据通信完全指南】从物理层到协议栈的深度解析

目录 1. 通信技术演进与核心挑战1.1 从电报到5G的技术变迁1.2 现代通信系统的三大瓶颈 2. 通信系统架构深度解构2.1 OSI七层模型运作原理2.2 TCP/IP协议栈实战解析 3. 物理层关键技术实现3.1 信号调制技术演进路线3.2 信道复用方案对比 4. 数据传输可靠性保障4.1 CRC校验算法数…

CMD与PowerShell:Windows命令行工具的对比与使用指南

CMD与PowerShell&#xff1a;Windows命令行工具的对比与使用指南 文章目录 CMD与PowerShell&#xff1a;Windows命令行工具的对比与使用指南引言1. CMD&#xff08;命令提示符&#xff09;简介1.1 什么是CMD&#xff1f;1.2 CMD的特点1.3 常用CMD命令示例1.4 CMD的优势与局限 2…

93. 后台线程与主线程更新UI Maui例子 C#例子

在.NET MAUI开发中&#xff0c;多线程是常见的需求&#xff0c;但UI更新必须在主线程上执行。今天&#xff0c;我们来探讨一个简单而优雅的解决方案&#xff1a;MainThread.InvokeOnMainThreadAsync。 一、背景 在跨平台应用开发中&#xff0c;后台线程常用于执行耗时操作&am…

海思正式公开了星闪BS21E的SDK

今天海思正式在Gitee平台发布了BS21E的SDK&#xff1a;fbb_bs2x: fbb_bs2x代码仓为支持bs21e解决方案SDK。技术论坛&#xff1a;https://developers.hisilicon.com/forum/0133146886267870001 fbb_bs2x代码仓为支持bs21e解决方案SDK&#xff0c;该SDK包从统一开发平台FBB&#…

QML学习:使用QML实现抽屉式侧边栏菜单

文章目录 前言一、环境配置二、实现步骤三、示例完整代码四、注意事项总结 前言 最近在进行QML的学习&#xff0c;发现一个比较有意思的交互设计&#xff1a;抽屉式侧边栏菜单&#xff0c;出于开发实战需求&#xff0c;最终实现了一个支持手势拖拽、弹性动画、蒙层效果和​​智…

峰终定律——AI与思维模型【85】

一、定义 峰终定律思维模型是指人们对一段经历的评价主要取决于这段经历中的高峰时刻&#xff08;无论是正向的还是负向的&#xff09;以及结束时的感受&#xff0c;而不是整个经历的平均感受。也就是说&#xff0c;如果在一段体验的高峰和结尾阶段给人们留下积极、强烈的印象…

【补题】Codeforces Round 664 (Div. 1) A. Boboniu Chats with Du

题意&#xff1a;给出n&#xff0c;d&#xff0c;m三个值&#xff0c;分别代表&#xff0c;有多少个值ai&#xff0c;使用超过m的ai&#xff0c;需要禁言d天&#xff0c;如果不足也能使用&#xff0c;m代表区分点&#xff0c;问能得到最大的值有多少。 思路&#xff1a; …

单片机与上位机串口通信:原理、应用与实践

注&#xff1a;本文为 “单片机与上位机串口通信” 相关文章合辑。 略作重排&#xff0c;未整理去重。 如有内容异常&#xff0c;请看原文。 单片机与上位机的串行通信 饕餮 tt 于 2019 - 12 - 06 14:47:19 发布 写在前面 本文主要记录单片机通过 TXD、RXD 与上位机进行数据…

996引擎-人物模型(UIModel):创建内观时装备偏移问题

996引擎-人物模型(UIModel):创建内观时装备偏移问题 创建 人物模型(UIModel)问题参考资料创建 人物模型(UIModel) 90、91 是自定义剑甲的穿戴位置,因为需求只需要显示剑甲,所以下面创建人物模型时,只给了剑甲的id、特效。 function Controller:updateUI()-- 自定义收拾…

Python小程序:上班该做点摸鱼的事情

系统提醒 上班会忘记一些自己的事&#xff0c;所以你需要在上班的的时候突然给你弹窗&#xff0c;你就知道要做啥了 源码 这里有一个智能家居项目可以看看(开源) # -*- coding:utf-8 -*- """ 作者:YTQ 日期: 2025年04日29 21:51:24 """ impor…

centos安装部署配置kafka

1、解压到目录 tar -zxvf kafka_2.13-2.8.2.tgz -C /usr/local/kafka2.进入目录 cd /usr/local/kafka/kafka_2.13-2.8.23.查看版本&#xff08;验证是否已解压&#xff09; bin/kafka-topics.sh --version4.修改配置&#xff0c;注意&#xff1a;此配置中有一个默认的zookee…

深⼊理解指针(7)

1.函数指针变量的创建 在x86环境下&#xff1a; 我们发现&#xff1a;以函数是有地址的&#xff0c;函数名就是函数的地址&#xff0c;当然也可以通过& 函数名 的⽅式获得函数的地址。 如果我们要将函数的地址存放起来&#xff0c;就得创建函数指针变量咯&#xff0c;函数…