推荐用 chi 路由器:路径参数用 {id} 并通过 chi.URLParam(r, “id”) 获取,查询参数需手动解析并封装为结构体;JSON 解析须用指针接收、导出字段加 json tag、补充业务校验;错误响应统一用 map[string]string 返回并设 http.StatusBadRequest;日志须用 zerolog/zap 等结构化库,注入 trace ID 到 context。
Go 语言写 RESTful API 不需要框架也能做,但用 net/http 手动处理路由、解析 JSON、错误响应容易漏掉边界情况;实际项目中推荐用轻量级路由器(如 gorilla/mux 或 chi),它们不侵入业务逻辑,又解决路径参数、中间件、预处理等刚需。
如何用 chi 定义带路径参数和查询参数的路由
chi 的路由语法简洁,支持嵌套和中间件,比原生 net/http 更易维护。路径参数用 {id} 表示,查询参数需手动从 r.URL.Query() 提取。
- 路径参数在 handler 中用
chi.URLParam(r, "id")获取,注意返回空字符串时需校验 - 查询参数如
?page=1&limit=20,建议封装一个parseQueryParams(r *http.Request)函数统一转成 struct,避免每个 handler 重复写strconv.Atoi - 不要把路径参数当可选字段用——
/users/{id}和/users必须分开注册,chi不会自动 fallback
示例:
router.Get("/users/{id}", getUserHandler)
router.Get("/users", listUsersHandler)
JSON 请求体解析失败时如何返回清晰错误
直接用 json.Unmarshal 解析 r.Body,出错时默认只返回 400 Bad Request,前端很难定位是字段名错了、类型不对,还是少了必填字段。
- 始终用指针接收结构体(
json.Unmarshal(r.Body, &req)),否则解析后字段值不会写入 - 结构体字段必须导出(首字母大写),且加
json:"field_name"tag,否则反序列化为零值 - 对关键字段加自定义校验(如
if req.Email == ""),别依赖json包的 “omitempty” 做业务判断 - 错误响应统一用
map[string]string{"error": "xxx"}格式,HTTP 状态码设为http.StatusBadRequest
为什么不要在 handler 里直接调用 log.Printf
看似方便,但会导致日志缺乏上下文(比如无法关联请求 ID、无法区分 debug/info/warn)、难以接入集中式日志系统,且并发写文件可能成为瓶颈。