生产环境不推荐直接用net/http写RESTful API,因其不处理路径参数、不校验Content-Type、易静默出错;gin通过c.Param()提取路径参数、c.ShouldBindJSON()自动校验类型与字段,配合标准状态码返回,显著提升健壮性与一致性。

直接用 net/http 能跑通 RESTful API,但生产环境不推荐——它不处理路径参数、不区分方法语义、不校验 Content-Type,容易返回 200 却实际出错,或静默丢数据。
为什么 http.HandleFunc 不适合写 REST 路由
它只是把路径字符串和函数绑在一起,所有逻辑得手动拆解:
-
r.URL.Path需要自己strings.Split截取/users/123中的 ID,/users/123/和/users/123被视为不同路径 -
r.Method == "POST"这类判断散落在各处,漏一个就导致 DELETE 请求被当 GET 处理 -
json.Unmarshal前不检查r.Header.Get("Content-Type"),遇到text/plain会报invalid character却没提示来源 - 空
r.Body或未关闭的 Body 会导致后续中间件读不到数据,甚至 panic
gin 中怎么正确提取路径参数和解析 JSON
:id 是命名参数,不是查询参数;c.Param("id") 返回的是字符串,必须手动转换并校验:
- 别用
c.Query("id")取路径段,那是为?id=123准备的 -
c.ShouldBindJSON(&u)会自动检查Content-Type和结构体字段标签(如binding:"required"),比手写json.Decode安全得多 - 如果 ID 必须是整数,记得用
strconv.Atoi(c.Param("id"))并判断 error,/users/abc也会被路由匹配到 - POST/PUT 请求若没带
Content-Type: application/json,ShouldBindJSON会直接返回 400,而不是继续执行 handler
gin.JSON() 默认不设状态码,这点非常容易忽略
调用 c.JSON(200, data) 看似没问题,但创建资源该用 http.StatusCreated,删除后该用 http.StatusNoContent。默认全 200 会让前端无法区分操作结果:
立即学习“go语言免费学习笔记(深入)”;
-
c.JSON(http.StatusOK, data)用于 GET 或 PUT 成功 -
c.JSON(http.StatusCreated, data)用于 POST 创建成功(且响应中应含Locationheader) - 返回空内容时用
c.Status(http.StatusNoContent),别传nil给JSON,否则输出{} - time.Time 字段默认序列化成 Go 内置格式(如
"2006-01-02T15:04:05Z"),如需 RFC3339,得全局替换json.Marshal或用jsoniter
真正难的不是写完第一个接口,而是让所有错误路径都返回一致的 JSON 结构、所有时间字段格式统一、所有 ID 校验不遗漏——这些细节在 net/http 里得每处重复写,在 gin 里靠中间件和绑定规则能收敛,但前提是知道哪些地方不能偷懒。


















