接口路径应体现资源语义而非动词,如/users表示用户集合、/users/123表示具体实例;HTTP方法对应CRUD操作;字段名需与模型一致并用json标签控制输出;错误响应须含machine-readable code和human-readable message;查询参数应明确、有限且带校验。

接口路径命名必须体现资源语义,而非动词操作
RESTful 风格下,/users 表示用户集合资源,/users/123 表示具体用户实例——这是 Gin 中最常被误用的点。很多开发者写成 /getUserById 或 /createUser,这破坏了资源抽象,导致前端无法通过统一方式推导路径结构。
实际开发中,Gin 路由应严格匹配 HTTP 方法语义:GET /users 查列表,POST /users 创建,PUT /users/123 全量更新,PATCH /users/123 局部更新,DELETE /users/123 删除。
- 避免在路径里塞业务动作,比如
/users/activate、/orders/cancel;这类操作应转为子资源(/users/123/status)或独立动作接口(POST /users/123/actions/activate) - 路径中不带查询参数语义,如
/users?status=active是合法的,但不能写成/users/active - 复数名词优先:用
/products,不用/product;即使只返回单个也保持复数形式(语义一致)
响应体字段名必须与数据库字段或领域模型对齐,禁止“驼峰转下划线”一刀切
Gin 默认使用 Go 结构体标签(如 json:"user_id")控制序列化输出,但很多团队盲目统一加 snake_case 标签,结果导致前端拿到 created_at 却要映射回 createdAt,徒增转换成本。
真正自解释的接口,字段名应直接反映业务含义,且前后端约定一致。Go 侧只需保证结构体字段名有意义(如 CreatedAt),再通过 json 标签显式声明前端所需格式:
立即学习“go语言免费学习笔记(深入)”;
type User struct {
ID uint `json:"id"`
Name string `json:"name"`
CreatedAt time.Time `json:"created_at"`
IsActive bool `json:"is_active"`
}
- 不要依赖第三方库自动转换(如
gin-contrib/sse或自定义 JSON marshaler),容易掩盖字段语义 - 枚举值字段(如
Status)必须用字符串字面量,而非数字码:"pending"比1更自解释 - 嵌套对象字段名也要保持一致性,比如
profile.avatar_url和profile.background_image命名逻辑需统一
错误响应必须携带 machine-readable code 和 human-readable message,且 code 不依赖 HTTP 状态码
仅靠 404 Not Found 或 500 Internal Server Error 无法支撑前端精细化错误处理。Gin 接口中常见错误如 “用户不存在”、“权限不足”、“余额不足”,每种都应有唯一、稳定的 code 字段(如 "USER_NOT_FOUND"),与 HTTP 状态码解耦。
典型响应结构应为:
{
"code": "USER_NOT_FOUND",
"message": "指定 ID 的用户不存在",
"details": {"user_id": "123"}
}
- HTTP 状态码用于表示通信层问题(如
400表请求格式错,401表未认证,403表无权限),业务错误一律用400或422,靠code区分语义 - 禁止把
code设为数字(如1001),易冲突且无意义;全部用大写下划线命名的字符串 - 所有错误响应统一走
c.AbortWithStatusJSON(),避免混用c.JSON()导致状态码和 body 不一致
查询参数设计要支持可预测的组合,拒绝“万能 query”
像 /users?filter=name:eq:john,status:in:active,inactive&sort=-created_at&limit=20 这类参数看似灵活,实则难测试、难缓存、难文档化。Gin 接口应提供明确、有限的查询维度,并为每个维度定义合法值范围。
推荐方式是拆分为独立参数,例如:
-
status:只接受active、inactive、deleted(后端校验,非法值直接400) -
name_like:模糊匹配用户名,长度限制 1–50 字符 -
page和size:分页参数,size最大限制为 100 - 不提供
order_by通配字段,而是固定支持sort=created_at,-updated_at
这样前端调用时,路径可读性强(/users?status=active&name_like=john&page=1&size=10),Swagger 文档也能准确生成参数说明,Nginx 缓存策略也更容易配置。
最容易被忽略的是:所有可选查询参数都应在 handler 中显式声明默认值,并做类型校验——Gin 的 c.Query() 返回字符串,不校验就直接传给数据库,极易引发 SQL 注入或 panic。


















