如何通过Gin中间件向HTML模板传递通用数据(Golang)
在Gin框架中通过中间件全局传递模板数据
当然可以通过Gin的中间件实现全局传递分类数据,无需在每个处理器中重复编写代码,以下是具体实现方案:
1. 编写全局分类中间件
先实现一个中间件,负责获取分类数据并存储到Gin Context的Keys中,后续的处理器和渲染逻辑都能访问到该数据:
import ( "sync" "github.com/gin-gonic/gin" ) // 假设你的分类结构体定义如下 type Category struct { ID uint Name string } var cachedCategories []Category var cacheMutex sync.RWMutex // CategoriesMiddleware 全局分类中间件,内置缓存优化避免重复查库 func CategoriesMiddleware(db *YourDBType) gin.HandlerFunc { return func(c *gin.Context) { // 优先从缓存读取分类数据 cacheMutex.RLock() categories := cachedCategories cacheMutex.RUnlock() // 缓存为空时,从数据库拉取并更新缓存 if categories == nil { cacheMutex.Lock() // 双重检查锁防止并发重复查库 if cachedCategories == nil { cachedCategories = db.GetCategories() } categories = cachedCategories cacheMutex.Unlock() } // 将分类数据存入Context c.Set("categories", categories) // 执行后续中间件与处理器 c.Next() } }
将中间件注册到全局路由:
r := gin.Default() // 传入你的数据库实例 r.Use(CategoriesMiddleware(yourDBInstance))
2. 自动合并全局数据到模板
有两种常用方式让模板自动获取Context中的分类数据:
方式一:自定义渲染函数(推荐)
封装自定义HTML渲染函数,自动合并Context中的分类数据与处理器传入的页面专属数据,无需手动重复添加:
// RenderHTML 自定义模板渲染函数,自动注入全局分类数据 func RenderHTML(c *gin.Context, status int, templateName string, data gin.H) { // 从Context取出分类数据 categories, exists := c.Get("categories") if exists { // 仅当处理器未传入categories时才注入,避免覆盖自定义数据 if _, hasCategory := data["categories"]; !hasCategory { data["categories"] = categories } } // 调用Gin原生HTML渲染逻辑 c.HTML(status, templateName, data) }
处理器中直接使用该函数,只需传入页面专属数据:
func HomeHandler(c *gin.Context) { RenderHTML(c, 200, "home.html", gin.H{ "title": "博客首页", "posts": getHomePagePosts(), }) }
方式二:模板函数直接读取Context
若不想自定义渲染函数,可在模板中注册函数直接从Context获取分类数据:
初始化模板时注册函数:
r.SetFuncMap(template.FuncMap{ "getGlobalCategories": func(c *gin.Context) []Category { cat, _ := c.Get("categories") return cat.([]Category) }, })
模板中直接调用该函数:
<!-- 导航栏分类下拉菜单 --> <div class="dropdown"> <button>分类</button> <div class="dropdown-content"> {{ range getGlobalCategories . }} <a href="/category/{{ .ID }}">{{ .Name }}</a> {{ end }} </div> </div>
注意事项
- 若分类数据会更新,需添加缓存刷新逻辑(如定时任务或更新分类时主动清空缓存)
- 中间件中数据库查询需添加错误处理,避免因DB异常阻塞请求
内容的提问来源于stack exchange,提问作者Ali Alhajji
相关产品推荐
相关产品推荐

