Files
Inbox/Go项目实战/02_接口设计/七七八八的接口设计相关问题.md
2025-12-11 07:24:36 +08:00

6.6 KiB
Raw Permalink Blame History

tags, aliases, date created, date modified
tags aliases date created date modified
1. 接口版本控制策略 (API Versioning Strategy)
星期日, 十二月 7日 2025, 11:38:52 晚上 星期日, 十二月 7日 2025, 11:42:18 晚上

七七八八的接口设计相关问题

1. 接口版本控制策略 (API Versioning Strategy)

核心问题: 当你发布了 V1 版本后,某天需要修改接口字段(比如把 name 拆分为 first_namelast_name),如何保证老版本的 App 不会崩溃?

三种主流流派:

  1. URI Path Versioning (推荐):

    • 格式: https://api.example.com/v1/users

    • 优点: 直观、易于调试、缓存友好。这也是 GitHub, Twitter, Google API 采用的主流方案。

    • 落地: 我们在 Gin 的 Router Group 中直接体现:

      Go

      v1 := r.Group("/api/v1")
      {
          v1.GET("/users", ...)
      }
      
  2. Header Versioning:

    • 格式: Header 中添加 Accept: application/vnd.myapi.v1+json
    • 优点: URL 干净。
    • 缺点: 调试麻烦(浏览器直接访问 URL 看不到结果CDN 缓存配置复杂。不推荐 MVP 阶段使用。
  3. Query Parameter:

    • 格式: /users?version=1
    • 评价: 看起来很土,通常不用于 RESTful API。

👉 你的策略: 坚定选择 URI Path Versioning (/api/v1)。只在发生破坏性变更 (Breaking Change) 时才升级到 v2。新增字段不算破坏性变更不需要升级版本。


2. HTTP 方法的精准语义 (Verbs Semantics)

很多新手只会用 GETPOST。企业级 API 必须精准区分以下方法的含义:

方法 语义 幂等性 (Idempotency) 典型场景
GET 获取资源 获取文章列表、详情
POST 新建资源 发布新文章、提交评论
PUT 全量替换资源 修改文章(客户端发送文章的完整 JSON没传的字段会被置空
PATCH 局部更新资源 否 (理论上) 修改文章状态(只传 {"status": "published"},其他字段不变)
DELETE 删除资源 删除文章

⚠️ 重点关注 PUT vs PATCH:

在 Go 语言中实现 PATCH 有点麻烦(因为 Go 的结构体默认值问题,你很难区分用户是传了 0 还是没传这个字段)。

  • 最佳实践: 对于 CMS 这种表单复杂的系统,修改接口首选 PUT (全量),或者针对特定状态修改提供独立接口(如 POST /articles/:id/publish)。如果必须做 PATCHDTO 需使用指针类型 *string 来判断是否为 nil

3. RESTful URL 设计模式 (Resource Naming)

原则URL 中只出现名词,不出现动词。

  • 反例 (RPC 风格 - 不要这么做):
    • /api/getUsers
    • /api/createUser
    • /api/deleteArticle?id=1
  • 正例 (REST 风格):
    • GET /api/v1/users (获取列表)
    • POST /api/v1/users (创建)
    • DELETE /api/v1/articles/1 (删除 ID 为 1 的文章)

复杂关系的嵌套设计:

  • 场景: 获取某篇文章下的评论。
  • 设计: GET /api/v1/articles/{article_id}/comments
  • 场景: 获取某个作者的所有文章。
  • 设计: GET /api/v1/users/{user_id}/articles

4. 列表接口三剑客:分页、排序、筛选 (Pagination, Sorting, Filtering)

你的 CMS 一定会有“文章列表”页面,这个接口是最复杂的。不要为每种查询都写一个新接口,要设计一个通用的查询接口

最佳实践标准:

  1. 分页 (Pagination):

    • 使用 page (页码) 和 page_size (每页条数)。
    • URL 示例: /articles?page=2&page_size=20
    • 注意: 要限制 page_size 的最大值(如 100防止恶意用户一次请求 100 万条数据把数据库打挂。
  2. 排序 (Sorting):

    • 使用 sort 参数。- 代表降序,无符号代表升序。
    • URL 示例: /articles?sort=-created_at (按创建时间倒序)
    • URL 示例: /articles?sort=view_count,-created_at (先按浏览量升序,再按时间倒序)
  3. 筛选 (Filtering):

    • 直接使用字段名作为参数。
    • URL 示例: /articles?category_id=1&status=published

5. 状态码与错误处理 (Status Codes & Error Handling)

不要永远只返回 200 OK

前端开发最恨的就是HTTP 状态码是 200结果 Body 里写着 {"code": 500, "msg": "Error"}。这会让监控系统失效。

你需要遵守的“HTTP 状态码地图”:

  • 2xx (成功):
    • 200 OK: 通用成功。
    • 201 Created: 创建成功 (POST 返回)。
    • 204 No Content: 删除成功 (DELETE 返回,不带 Body)。
  • 4xx (客户端错误 - 前端背锅):
    • 400 Bad Request: 参数校验失败(如邮箱格式不对)。
    • 401 Unauthorized: 未登录/Token 过期。
    • 403 Forbidden: 登录了,但没权限(如普通用户想删文章)。
    • 404 Not Found: 资源不存在。
  • 5xx (服务端错误 - 你背锅):
    • 500 Internal Server Error: 代码崩了/数据库挂了。

统一错误响应格式 (JSON Envelope):

无论发生什么错误Body 必须保持结构一致,方便前端拦截:

JSON

{
  "code": 40001,           // 业务错误码 (你在 pkg/e 定义的)
  "message": "标题已存在",   // 给用户看的提示
  "request_id": "abc-123"  // 方便查日志的 Trace ID
}

6. 进阶知识:幂等性 (Idempotency)

概念: 用户因为网络卡顿,连续点击了 3 次“发布文章”按钮,你的系统会创建 1 篇文章还是 3 篇?

  • 非幂等: POST。点 3 次创建 3 篇。
  • 幂等: PUT / DELETE。改 3 次和改 1 次结果一样;删 3 次和删 1 次结果一样(都是没了)。

如何处理 POST 的幂等性?

对于关键业务(如支付、核心数据创建),通常要求前端在 Header 带一个 Idempotency-Key (UUID)。后端 Redis 记录这个 Key如果短时间内收到相同的 Key直接返回上次的结果不执行数据库插入。

(注MVP 阶段可以先不做,但面试或者做高可靠系统时必须知道)


总结:在你开始定义 API 之前

请在心中建立这套标准:

  1. URL: /api/v1/名词
  2. Method: 查询用 GET新建用 POST修改用 PUT删除用 DELETE。
  3. List: 永远记得预留 page, page_size
  4. Response: 永远返回统一的 JSON 结构,报错必须用 4xx/5xx 状态码。

准备好了吗?我们可以开始基于这些原则,设计 User 模块的 API 了。