chi.router 必须用 chi.newrouter() 初始化,因其是接口而非结构体,直接 chi.router{} 会导致 nil dereference panic;中间件需在路由注册前调用;路径参数须用 chi.urlparam 提取;嵌套路由应使用 group 而非字符串拼接。

chi.Router 必须用 chi.NewRouter() 初始化,直接写 chi.Router{} 会 panic。
chi.Router 是接口,不是结构体
很多人看到文档里类型是 chi.Router,就以为能像普通结构体一样字面量初始化:router := chi.Router{}。结果一调 Use 或 Get 就报 panic: runtime error: invalid memory address —— 因为它根本没实现任何方法。
chi.Router 是个接口,真正干活的是内部的 *mux(一个指针类型)。只有 chi.NewRouter() 才返回这个有效实例。
- 错误写法:
router := chi.Router{}→ 空接口值,所有方法调用都 nil dereference - 正确写法:
router := chi.NewRouter()→ 返回带完整方法绑定的*mux - 想复用路由逻辑?封装成函数返回
chi.Router,别试图“构造”它
中间件顺序错位导致 context.Value 为空
你写了 router.Use(authMiddleware),但 handler 里 r.Context().Value("user") 还是 nil?大概率是中间件注册太晚了。
chi 的中间件只对「注册之后」添加的路由生效。一旦路由(比如 router.Get("/api/user", h))先注册了,再 Use 中间件,那条路由就永远收不到。
开箱即用的技能链路由引擎。13 条预定义链覆盖搜索、开发、审查、MLOps、法律、创意等场景,三层路由架构(触发词→SAD反馈→DAG编排),recall@10=96.97%。配置驱动(chains.yaml),零代码扩展。pip install skill-weave-chains 一键安装。
- 全局中间件必须在任何
Get/Post之前调用Use -
chi.With()创建的是新子路由器,它的中间件不会透传给Mount或Group里的路由 - 日志、recover、JWT 验证这类关键中间件,必须放在最外层,否则可能压根不执行
路径参数必须用 chi.URLParam 提取
访问 /user/123?format=json,却在 handler 里写 r.URL.Query().Get("id") → 总是空。因为 {id} 是路径参数,不是查询参数。
chi 不会把路径参数塞进 r.URL.Query(),它存在内部匹配结果里,只能通过 chi.URLParam(r, "id") 安全读取。
-
chi.URLParam(r, "id")返回空字符串(不是 panic),但你要自己判空 - 参数名大小写敏感:路由定义是
/user/{id},就不能写chi.URLParam(r, "ID") - 别碰
r.URL.Path字符串切分,URL 编码、嵌套路由、边界情况都会让你掉坑里
嵌套路由该用 Group 而非字符串拼接
想给所有 API 加 /api/v1 前缀,别手写 router.Get("/api/v1/users", ...) 二十遍。更糟的是,有人用变量拼接:prefix + "/users" —— 这会让路由树失去结构,中间件无法按组隔离,测试和维护全乱套。
Group 是 chi 提供的语义化嵌套机制,它创建的是独立中间件栈 + 共享前缀的子路由器。
- 正确方式:
router.Group(func(r chi.Router) { r.Use(auth); r.Get("/users", h) }) - 前缀自动处理,
Group内写的/users会自动变成/api/v1/users(如果外层Mount("/api/v1", sub)) - 每个
Group可单独加中间件,比如公共路由限流 100qps,私有路由限流 10qps
chi 的核心陷阱不在功能多难,而在它太轻——轻到容易忽略类型本质、执行时序和参数边界。写完 chi.NewRouter() 后第一件事,不是加路由,是检查中间件是否已在最顶上;提取参数前,先确认你用的是 chi.URLParam 而不是自己解析 URL 字符串。
golang免费学习笔记(深入):立即使用
在学习笔记中,你将探索golang的核心概念和高级技巧!










