选 net/http 还是 gin?小项目或学原理用 net/http 更扎实;快速交付且需 JWT、Swagger 时选 gin,但须加 recovery 中间件防 panic。

用 net/http 还是 gin?选框架前先看这三点
Go 写 RESTful 服务,net/http 足够轻量、无依赖,但路由注册、参数解析、错误统一处理都得手写;gin 是最常用的选择,性能好、中间件生态成熟,但要注意它默认不校验 Content-Type,且 gin.Context.BindJSON() 在请求体为空或格式非法时直接 panic(不是返回 400),新手容易掉坑。
- 小项目或想彻底理解 HTTP 处理流程,从
net/http+http.ServeMux入手更扎实 - 需要快速交付、带 JWT 鉴权或 Swagger 文档,
gin更省事,但务必加recovery中间件兜底 - 别用
echo或fiber做第一个项目——它们对 Go 新手隐藏太多底层细节,出错时 debug 成本更高
RESTful 路由设计:别把 /user/{id} 当万能模板
Go 的路由库(包括 gin 和 gorilla/mux)本身不强制 REST 规范,全靠开发者约定。常见错误是把所有操作塞进 GET /user/{id},再靠 query 参数区分行为(比如 ?action=delete),这违反 REST 原则,也导致缓存、代理、CDN 行为不可控。
-
POST /users创建用户(body 传 JSON) -
GET /users列表(支持?page=1&limit=20) -
GET /users/{id}单条({id}必须是 UUID 或数字,避免用邮箱等含特殊字符的字段) -
PATCH /users/{id}局部更新(不是PUT—— 后者要求客户端提供完整资源) -
DELETE /users/{id}删除(别返回 body,只返回 204)
注意:gin 中注册 PATCH 路由要显式写 r.PATCH(...),不能只靠 Any() 或 Handle() 模糊匹配。
请求体解析:BindJSON 的三个陷阱
gin.Context.BindJSON() 看似方便,但新手常因结构体标签、空值处理、嵌套字段而失败。它底层调用 json.Unmarshal,但错误不透出,只返回 400 Bad Request,很难定位具体哪一行 JSON 出问题。
- 结构体字段必须首字母大写 +
json:"xxx"标签,否则解析永远为零值 - 想接收可选字段,用指针类型:
Name *string `json:"name"`,而不是string - 嵌套对象必须定义独立 struct,不能用
map[string]interface{}—— 否则BindJSON不会报错,但字段全为零值
type CreateUserRequest struct {
Name string `json:"name" binding:"required"`
Age *int `json:"age"`
Tags []string `json:"tags"`
}
func handleCreate(c *gin.Context) {
var req CreateUserRequest
if err := c.ShouldBindJSON(&req); err != nil { // 用 ShouldBindJSON 替代 BindJSON,避免 panic
c.JSON(400, gin.H{"error": err.Error()})
return
}
// ...
}
状态码与错误响应:别只写 200 和 500
一个规范的 RESTful 接口,状态码本身就是契约的一部分。net/http 默认返回 200,gin 也一样。但实际场景中,404(资源不存在)、409(冲突,如用户名已存在)、422(语义错误,如邮箱格式不对)都该明确返回。
- 不要用
c.JSON(200, ...)返回错误信息 —— 这会让前端无法用 HTTP 状态码做统一拦截 - 404 场景:查数据库没结果,就该
c.Status(404),而不是返回{"code":404,"msg":"not found"} - 业务错误建议封装成结构体,但状态码必须真实:
type ErrorResponse struct { Code int `json:"code"` Message string `json:"message"` } // 但发送时仍用 c.JSON(code, errResp),且 code 必须和 HTTP 状态码一致
最容易被忽略的是 422 和 400 的区分:400 是客户端发了根本无法解析的请求(如非 JSON body),422 是 JSON 格式正确但业务字段不合法(如 email 缺 @ 符号)—— Gin 的 binding 标签校验失败默认返回 400,需手动转成 422。










