不能用c.Set()传用户ID、租户ID,因其仅限当前Echo context生效,不透传至后续中间件或下游库(如sqlx、zerolog),且无类型安全与IDE提示;应使用context.WithValue()配合自定义key写入c.Request().Context()并确保下游调用均使用...Context()版本函数。

直接往 c.Request().Context() 里塞值是最稳妥的传递方式,c.Set() 只在当前 Echo context 生效,跨中间件或下游库(如数据库、日志)就失效了。
为什么不能用 c.Set() 传用户 ID、租户 ID 这类关键上下文
常见错误现象:c.Set("user_id", 123) 后,下一个中间件调用 c.Get("user_id") 返回 nil;DB 层用 sqlx.QueryRowContext(c.Request().Context(), ...) 拿不到值,审计日志全空。
-
c.Set()的数据不自动透传给后续中间件,除非显式调用c.Get(),且只对当前echo.Context实例有效 - 第三方库(如
sqlx、zerolog)只认http.Request.Context(),完全无视c.Set() - 字符串键易拼错、无类型检查、IDE 不提示,线上 debug 时容易卡在 “值哪去了”
怎么安全地把 request_id、user_id 塞进 Context 并取出来
必须用自定义 key 类型 + context.WithValue(),再通过 c.SetRequest() 更新请求对象。
开箱即用的技能链路由引擎。13 条预定义链覆盖搜索、开发、审查、MLOps、法律、创意等场景,三层路由架构(触发词→SAD反馈→DAG编排),recall@10=96.97%。配置驱动(chains.yaml),零代码扩展。pip install skill-weave-chains 一键安装。
- 定义强类型 key:
type ctxKey string,然后const userIDKey ctxKey = "user_id" - 中间件中写入:
ctx := c.Request().Context()→newCtx := context.WithValue(ctx, userIDKey, uint64(123))→c.SetRequest(c.Request().WithContext(newCtx)) - handler 中读取:
v, ok := c.Request().Context().Value(userIDKey).(uint64),别用c.Get()混淆路径 - 所有下游组件(DB 查询、logger 写入)都必须用
c.Request().Context()发起调用,否则白塞
路由分组和中间件顺序对 Context 传递的影响
嵌套分组(比如 e.Group("/api").Group("/v1").Group("/users"))会导致中间件执行链断裂,Context 被多次包装但未正确透传,最终 handler 拿到的是原始空 context。
- 按业务域扁平分组:
userGroup := e.Group("/api/v1/users"),不是按 HTTP 方法或版本嵌套 - 中间件注册顺序决定
Context包装顺序:认证中间件必须在日志/DB 中间件之前,否则后者的 context 里没 user_id - 避免在 Group 上重复挂同一中间件(如两次
Use(middleware.Logger)),会叠加 context 包装,增加 GC 和类型断言开销
真正麻烦的不是“怎么塞”,而是“谁在用这个 Context”——只要有一个下游调用漏掉 ...Context() 版本函数(比如用了 sqlx.QueryRow() 而非 QueryRowContext()),整个链路就断了。这点很容易被忽略,尤其在引入新 SDK 时。


















