ctx.values() 是 iris 中唯一推荐的请求内临时数据存储方式,基于 sync.map 实现线程安全,需用自定义类型作 key 并在中间件中 next() 前调用 set,与标准库 context.context.value 完全隔离。

ctx.Values() 是唯一推荐的临时数据存储方式
Iris 的 Context 不是通用状态容器,它只服务于单次 HTTP 请求生命周期。跨请求存值(比如登录态)必须用 Session、JWT 或外部存储,而请求内中间件与 handler 之间传参,ctx.Values() 是官方唯一支持且线程安全的机制。
它底层基于 sync.Map 实现,所有 Set/Get 操作自动加锁,无需额外同步处理。但注意:key 类型建议用自定义常量类型(如 type userIDKey struct{}),避免字符串拼写错误导致取不到值。
-
ctx.Set("user_id", 123)和ctx.Values().Get("user_id")配对使用最直观,但 key 冲突风险高 - 更稳妥的做法是定义 key 类型:
var userIDKey = struct{}{},然后ctx.Set(userIDKey, 123) - 不要用
ctx.Values().Set直接操作 map —— 这个方法已被弃用,新版 Iris 会 panic
中间件里 Set,Handler 里 Get 是标准流程
常见错误是把 ctx.Set() 放在 Next() 之后,导致后续 handler 拿不到值。Iris 的执行顺序是「中间件 → handler → 中间件 return」,所以赋值必须在 Next() 前完成。
典型结构如下:
app.Use(func(ctx iris.Context) {
// ✅ 正确:在 Next() 前设值
ctx.Set("auth_level", "admin")
ctx.Next()
// ❌ 错误:这里设值对 handler 不可见
})
app.Get("/profile", func(ctx iris.Context) {
level := ctx.Values().Get("auth_level") // 能拿到 "admin"
ctx.JSON(iris.Map{"level": level})
})
- 如果 handler 中
Get返回nil,优先检查是否漏掉ctx.Next()或中间件未被注册 - 多个中间件连续调用时,后注册的中间件会先执行,值会被覆盖 —— 注意注册顺序
-
ctx.Values()不支持嵌套结构体自动解包,传 struct 没问题,但取的时候要类型断言完整
Values() 和 Request().Context() 完全无关
新手容易混淆 iris.Context.Values() 和 Go 标准库的 context.Context。前者是 Iris 自定义的请求级键值容器,后者是 Go 的取消/超时控制机制。Iris 的 Context 虽然实现了 context.Context 接口,但 Values() 方法不走它的 Value() 链路,两者数据完全隔离。
- 不要试图用
ctx.Request().Context().Value(key)去读ctx.Set()存的值 —— 一定为空 - 也不要用
context.WithValue()包装 Iris 的Context,这会导致类型断言失败或 panic - 需要传递取消信号时,用
ctx.Request().Context().Done();需要传业务数据时,只用ctx.Values()
性能和内存泄漏风险点
ctx.Values() 在每次请求结束时由 Iris 自动清空,理论上不会泄漏。但若在中间件中存了大对象(比如整个数据库连接、未关闭的文件句柄),或存了闭包引用了外部变量,就可能拖慢 GC 或引发泄漏。
- 避免存指针指向长生命周期对象,尤其不要存
*sql.DB或http.Client - 存 map/slice 时注意深拷贝 —— 如果 handler 修改了这个 slice,会影响其他中间件逻辑
- 调试时可用
ctx.Values().VisitAll(func(k interface{}, v interface{}) { ... })查看当前所有键值,但别在生产环境频繁调用











