当前位置: 首页 > article >正文

Gin:自定义日志、验证器与中间件全指南

前言在使用 Gin 开发 Web 服务时默认的功能已经能覆盖大部分场景但在生产环境中我们往往需要更精细的控制——比如定制日志格式以便于 ELK 采集、增加业务专属的参数校验规则、或者编写通用的请求拦截中间件。Gin 本身提供了非常优雅的扩展机制本文将结合四个实际示例带你彻底掌握 Gin 中四个常用自定义能力的实现方法。自定义HTTP访问日志格式Gin默认的访问日志长这样[GIN] 2023/04/19 - 10:41:52 | 200 | 122.767µs | ::1 | GET /ping虽然信息完整但格式较为固定。如果我们需要与现有日志平台对接或希望记录更多字段例如 User-Agent、错误信息等可以使用gin.LoggerWithFormatter自定义日志输出格式。func main() { router : gin.New() // 使用自定义格式的日志中间件 router.Use(gin.LoggerWithFormatter(func(param gin.LogFormatterParams) string { // 返回你想要的日志行格式 return fmt.Sprintf(%s - [%s] \%s %s %s %d %s \%s\ %s\\n, param.ClientIP, //用户ipv6地址 param.TimeStamp.Format(time.RFC1123), //访问时间 param.Method, //访问方法 param.Path, //访问路径 param.Request.Proto, //http版本 param.StatusCode, //状态码 param.Latency, //请求处理耗时 param.Request.UserAgent(), //客户端User-Agent头 param.ErrorMessage, //错误信息 ) })) router.Use(gin.Recovery()) router.GET(/ping, func(c *gin.Context) { c.String(200, pong) }) router.Run(:8080) }如果想输出到文件中可以这样做f, _ : os.Create(gin.log) gin.DefaultWriter f自定义路由日志在启动 Gin 服务时控制台会打印所有注册的路由信息[GIN-debug] POST /foo -- main.main.func1 (3 handlers) [GIN-debug] GET /bar -- main.main.func2 (3 handlers) [GIN-debug] GET /status -- main.main.func3 (3 handlers)这些信息对调试很有帮助但格式无法变更。Gin 提供了gin.DebugPrintRouteFunc变量允许我们接管路由日志的输出。func main() { r : gin.Default() gin.DebugPrintRouteFunc func(httpMethod, absolutePath, handlerName string, nuHandlers int) { // 方法资源路径函数名函数个数 log.Printf(endpoint %v %v %v %v\n, httpMethod, absolutePath, handlerName, nuHandlers) } r.POST(/foo, func(c *gin.Context) { c.JSON(http.StatusOK, foo) }) r.GET(/bar, func(c *gin.Context) { c.JSON(http.StatusOK, bar) }) r.GET(/status, func(c *gin.Context) { c.JSON(http.StatusOK, status) }) r.Run() }示例输出[GIN-debug] [WARNING] Creating an Engine instance with the Logger and Recovery middleware already attached. [GIN-debug] [WARNING] Running in debug mode. Switch to release mode in production. - using env: export GIN_MODErelease - using code: gin.SetMode(gin.ReleaseMode) [GIN-debug] [WARNING] You trusted all proxies, this is NOT safe. We recommend you to set a value. Please check https://github.com/gin-gonic/gin/blob/master/docs/doc.md#dont-trust-all-proxies for details. [GIN-debug] Environment variable PORT is undefined. Using port :8080 by default [GIN-debug] Listening and serving HTTP on :8080 2026/04/19 10:41:52 endpoint POST /foo main.main.func2 3 2026/04/19 10:41:52 endpoint GET /bar main.main.func3 3 2026/04/19 10:41:52 endpoint GET /status main.main.func4 3可以看到最后三行就是我们自己设置的路由日志了自定义参数验证器Gin 内置的binding标签提供了常用验证规则如required、email、gt等但在实际业务中我们常常需要定制校验逻辑比如判断日期是否晚于今天、字段值是否在指定范围内等。下面我们为Booking结构体的日期字段实现一个bookabledate验证规则要求日期不能早于今天。func main() { r : gin.Default() if v, ok : binding.Validator.Engine().(*validator.Validate); ok { v.RegisterValidation(bookabledate, bookleDate) } r.GET(/bookdate, getBookable) r.Run(:8080) } // 验证输入输出 // required:字段不能缺失bookabledate:自定义规则由后续函数实现 // gtfieldCheckIn:CheckOut必须大于CheckIntime_format:指定日期格式2006-01-02 type booking struct { CheckIn time.Time form:check_in binding:required,bookabledate time_format:2006-01-02 CheckOut time.Time form:check_out binding:required,gtfieldCheckIn,bookabledate time_format:2006-01-02 } // 验证实现函数,日期要晚于今日 var bookleDate validator.Func func(f validator.FieldLevel) bool { date, ok : f.Field().Interface().(time.Time) if ok { today : time.Now() // 验证日期是否在date之后 if today.After(date) { return false } } return true } func getBookable(c *gin.Context) { var b booking if err : c.ShouldBindWith(b, binding.Query); err nil { c.JSON(http.StatusOK, gin.H{message: 时间验证通过}) } else { c.JSON(http.StatusBadRequest, gin.H{error: 时间要在今天之后}) } }自定义中间件中间件是 Gin 最强大的功能之一。通过编写自定义中间件我们可以实现请求计时、鉴权、日志记录、请求体修改等通用逻辑。中间件执行流程:当一个请求到达 Gin 时它会按顺序执行所有已注册的中间件。如果在中间件中调用了c.Next()则会先执行后续的中间件和最终的路由处理函数待它们全部返回后再继续执行c.Next()后面的代码。func main() { // 创建一个没有中间件的gin引擎 r : gin.New() // 添加自定义的中间件 r.Use(Logger()) r.Use(SetDate()) // 设置响应路由 r.GET(/:name, func(c *gin.Context) { // 从上下文获取值 say : c.MustGet(say).(string) // 解析uri中的参数 name : c.Param(name) // 由于处理太快输出日志总是0s所以sleep 1纳秒 time.Sleep(1) c.String(http.StatusOK, Hello %s,%s, name, say) }) r.Run(:8080) } // 自定义中间件自定义一个计算其他所有中间件总耗时的中间件 func Logger() gin.HandlerFunc { return func(c *gin.Context) { // 记录请求的时间 t : time.Now() // 暂停当前函数调用后续所有中间件和路由处理函数 c.Next() // 计算总耗时 latency : time.Since(t) // 输出所用时间 log.Print(latency) } } // 自定义中间件用于在上下文写入数据供后续使用 func SetDate() gin.HandlerFunc { return func(c *gin.Context) { c.Set(say, 欢迎来到本站) } }输出结果2026/04/19 11:26:45 508.6µs可以看到通过自定义各种中间件可以得到自己想要的数据或完成想要的功能比如看请求到响应完成的总耗时。总结Gin 的扩展性设计非常优秀通过上述四个方向的自定义能力开发者可以轻松实现自定义方向核心 API / 方法主要用途访问日志格式gin.LoggerWithFormatter定制 HTTP 请求日志样式和输出目标路由注册日志gin.DebugPrintRouteFunc修改启动时路由信息的打印方式参数验证规则binding.Validator.Engine().RegisterValidation添加业务专属的参数校验逻辑中间件gin.HandlerFuncc.Next()实现请求拦截、预处理、后处理掌握这些自定义技巧能够让你的 Gin 应用更加健壮、可观测、易维护更好地适应生产环境的复杂需求。

相关文章:

Gin:自定义日志、验证器与中间件全指南

前言在使用 Gin 开发 Web 服务时,默认的功能已经能覆盖大部分场景,但在生产环境中我们往往需要更精细的控制——比如定制日志格式以便于 ELK 采集、增加业务专属的参数校验规则、或者编写通用的请求拦截中间件。Gin 本身提供了非常优雅的扩展机制&#x…...

新消费进入下半场:情绪消费成为新的增长引擎

如果把过去几年新消费的发展放在一条时间线上看,会有一个很明显的分水岭。前一阶段,品牌增长主要靠三件事:渠道红利、流量效率、供应链能力。谁更快铺渠道,谁更会投放,谁更能把成本打下来,谁就更容易跑出来…...

Degrees of Lewdity中文汉化版:完整安装指南与终极教程

Degrees of Lewdity中文汉化版:完整安装指南与终极教程 【免费下载链接】Degrees-of-Lewdity-Chinese-Localization Degrees of Lewdity 游戏的授权中文社区本地化版本 项目地址: https://gitcode.com/gh_mirrors/de/Degrees-of-Lewdity-Chinese-Localization …...

MATLAB代码:双层优化微电网系统规划设计方法——多电源容量优化配置与最佳运行策略研究

MATLAB代码:基于双层优化的的微电网系统规划设计方法 关键词:双层优化 容量配置 参考文档:《基于双层优化的的微电网系统规划设计方法》基本复现 仿真平台:MATLABCPLEX 与目前大部分的微网优化调度代码不同,本代码主…...

[特殊字符] Meixiong Niannian画图引擎效果实测:1024×1024输出在印刷级DPI下的表现

Meixiong Niannian画图引擎效果实测:10241024输出在印刷级DPI下的表现 1. 项目概述 Meixiong Niannian画图引擎是一款专为个人GPU设计的轻量化文本生成图像系统。该系统基于Z-Image-Turbo底座,深度融合了Niannian专属Turbo LoRA微调权重,针…...

Cadence Allegro 17.4 建库避坑指南:从PAD丢失到Pin One属性,新手常踩的5个雷

Cadence Allegro 17.4 建库避坑指南:从PAD丢失到Pin One属性,新手常踩的5个雷 刚接触Cadence Allegro的硬件工程师,在建库过程中总会遇到各种"坑"。这些看似简单的问题,往往让人耗费数小时却找不到解决方案。本文将针对…...

手把手教你用网线搞定华为S5735S交换机堆叠(iStack实战避坑)

华为S5735S交换机零成本堆叠实战:用网线搭建高可靠网络 在中小企业网络升级过程中,端口扩展和链路冗余往往是刚需,但专用堆叠模块和光模块的高成本常常让预算有限的网管望而却步。华为S5735S系列交换机支持通过普通以太网电口(即R…...

SeanLib系列函数库-MyTimer

查看其它库函数说明,请点击此处跳转到SeanLib主页 1. 本篇内容 本篇讲MyTimer,是一个轻量级的软件定时器/计数器库,基于链表实现,支持动态创建和销毁定时器。适用于嵌入式系统(如 STM32、AVR、ESP32 等平台&#xff…...

VS2019下OpenCV C++环境配置保姆级教程(附4.4.0版本动态库文件清单)

VS2019与OpenCV C环境配置:从避坑到精通的完整指南 在计算机视觉开发领域,OpenCV无疑是最受欢迎的库之一。然而对于刚接触C开发的初学者来说,配置开发环境往往成为第一道门槛。本文将深入剖析VS2019下OpenCV C环境配置的关键细节,…...

图论——拓扑排序(python)

思路:统计节点的入度,将入度为0的节点放入队列中,循环出队。对于出队元素,找到它指向的所有元素,将所指向的元素的入度减一。#拓扑排序 from collections import deque def topologicalOrder(graph,indegree,n):qdeque…...

训练时train loss和val loss的‘爱恨情仇’:从曲线看懂模型到底在干嘛(附调参实战)

训练时train loss和val loss的‘爱恨情仇’:从曲线看懂模型到底在干嘛(附调参实战) 盯着训练日志里两条纠缠不清的loss曲线,是不是像在看一场情感大戏?train loss像热情似火的追求者,val loss则像若即若离的…...

保姆级教程:用VMware Workstation Pro搭建CFS三层靶场(附宝塔面板配置与网络排错)

零基础搭建CFS三层靶场:从VMware配置到宝塔面板全攻略 在网络安全学习过程中,环境搭建往往是新手遇到的第一个"拦路虎"。很多初学者满怀热情下载了靶机镜像,却在VMware网卡配置、IP设置、服务访问等环节频频受阻,最终连…...

树莓派PICO的‘Hello World’:用MicroPython和Thonny让板载LED闪起来(含代码详解)

树莓派PICO的‘Hello World’:用MicroPython和Thonny让板载LED闪起来(含代码详解) 当你第一次拿到树莓派PICO这块小巧的开发板时,最令人兴奋的莫过于让它"活"起来——而让板载LED闪烁就是嵌入式世界的"Hello World…...

Dify企业权限配置避坑指南(2024最新LTS版实测):92%团队踩过的5个ACL配置陷阱全复盘

第一章:Dify企业级权限管控配置概览Dify 作为开源大模型应用开发平台,其企业版提供了细粒度、可扩展的权限管控体系,覆盖组织、团队、应用、数据集及知识库等多个维度。权限模型基于 RBAC(基于角色的访问控制)设计&…...

深入理解传输中二层PW和三层BFD之间的关系

这段输出已经把 PW BFD 的关系展示得比较典型了,可以直接帮你把结构“还原出来”。一、先看 PW(业务层) 命令: show mpls l2transport vc vl1关键结果: DestAddress: 3.13.77.14 VCID: 32008578 Status: up S VCI…...

通过dis dev pic看板卡的门道

这个命令: display device pic-status是查看设备 PIC 板卡(接口子卡)运行状态 的,用来确认板卡是否识别正常、初始化是否成功、端口逻辑状态是否正常。一、命令作用 display device pic-status查看内容: 设备各槽位接口…...

EF Core 10 + ChromaDB/Weaviate双模式接入方案(轻量嵌入式vs分布式向量库),企业级选型决策树首次披露

第一章:EF Core 10 向量搜索扩展的核心定位与演进脉络EF Core 10 向量搜索扩展并非孤立的功能补丁,而是微软在 .NET 生态中构建 AI 原生数据访问层的关键落子。它将传统关系型查询能力与现代向量相似性检索深度融合,使开发者能在同一 ORM 抽象…...

PolarloTS个人挑战赛第一季 个人WP

简单locke-treasure逆向狂喜void __fastcall decrypt_flag_to_buf(const unsigned __int8 *enc,int enc_len,const char *key,char *out_buf,int out_buf_len) {int key_len; // [rsp24h] [rbp4h]int i; // [rsp44h] [rbp24h]j___CheckForDebuggerJustMyCode(&_68090DB3_ca…...

别再只盯着压差了!手把手教你从PSRR、噪声到环路补偿,全面评估一颗LDO芯片

从PSRR到环路稳定性:LDO芯片的深度评估指南 在电子系统设计中,低压差稳压器(LDO)的选择往往被简化为"压差越低越好"的单一标准。这种认知偏差导致许多工程师在电源设计上踩坑——噪声干扰、系统振荡、效率低下等问题频发。本文将打破常规认知框…...

WGLOG日志审计系统可以支持数据库日志审计吗

支持的 WGLOG从v2.0开始支持数据库日志审计功能 下载地址:www.wgstart.com...

别再搞混了!一文讲透GIS中.tfw、GDAL、ArcMap的仿射变换六参数对应关系

地理空间数据处理中的仿射变换六参数全解析 当你在处理遥感影像或地图数据时,是否曾被不同GIS工具中的六参数搞得晕头转向?今天我们就来彻底理清.tfw文件、GDAL库和ArcMap中这些神秘数字的对应关系。无论你是GIS开发工程师还是空间数据分析师&#xff0c…...

从FPGA转岗数字IC SOC设计,我踩过的那些坑和必备技能清单(附学习路线)

从FPGA到数字IC SOC设计:一位工程师的转型实战指南 当我在FPGA领域深耕五年后,突然意识到自己站在了一个职业发展的十字路口。那些曾经让我兴奋的Verilog模块设计和时序优化,如今已变成日常的重复劳动。直到一次偶然的机会,我接触…...

企业媒体发布技术化转型:Infoseek舆情系统架构分析与应用实践

摘要在信息碎片化与网络舆论复杂化的背景下,传统媒体发布模式面临渠道不透明、内容适配效率低、舆情响应滞后三大技术性难题。本文从系统架构与应用实践角度,分析Infoseek字节探索推出的数字公关AI中台PaaS系统,重点探讨其融媒体发布模块如何…...

别再只当下载器了!手把手教你用Keil+STLink/JLink玩转STM32在线调试与变量监视

从烧录到调试:解锁STM32开发中仿真器的完整潜力 当你第一次拿到STM32开发板时,可能只把STLink或JLink当作一个简单的程序下载工具。但事实上,这些仿真器隐藏着强大的调试能力,能够彻底改变你的开发体验。想象一下,你可…...

OpCore-Simplify:10分钟自动化完成黑苹果配置的智能解决方案

OpCore-Simplify:10分钟自动化完成黑苹果配置的智能解决方案 【免费下载链接】OpCore-Simplify A tool designed to simplify the creation of OpenCore EFI 项目地址: https://gitcode.com/GitHub_Trending/op/OpCore-Simplify 还在为复杂的OpenCore配置而头…...

python codefresh

# 关于 Python Codefresh 的一些理解 最近在和一些做 DevOps 的朋友聊天时,发现不少人开始关注 Codefresh 这个工具,特别是它在 Python 项目中的应用。作为一个在 Python 领域摸爬滚打多年的开发者,也花时间研究了一下这个东西,有…...

Ryzen SDT 1.37:深度解析AMD处理器底层调试与性能调优工具

Ryzen SDT 1.37:深度解析AMD处理器底层调试与性能调优工具 【免费下载链接】SMUDebugTool A dedicated tool to help write/read various parameters of Ryzen-based systems, such as manual overclock, SMU, PCI, CPUID, MSR and Power Table. 项目地址: https:…...

Python提高:条件断点的详解-由Deepseek产生

条件断点详解 条件断点(Conditional Breakpoint)是调试器中的一项高级功能:只有当用户指定的条件表达式为真(True)时,程序才会在该断点处暂停。 它解决了“普通断点会每次中断,导致大量无意义停…...

在博客的第一遍文章

大家好,我是一名信息安全专业的大学生,很高兴认识大家,这是我的第一篇博客。1.编程的目标我希望学完编程之后,我能够随心所欲的用编程实现脑中的想法,把编程当成一个得心应手的工具2.如何去学习编程我觉得编程最重要的…...

OZON运营全场景导入,Captain AI系统功能适配效果

OZON运营涵盖新品选品、新品启动、合规申报、物流规划、核算复盘等多个核心场景,每个场景都有其独特的运营痛点与需求。Captain AI系统针对各核心场景,打造了专属功能适配方案,有效解决场景痛点,提升运营效果。一、OZON运营核心场…...