写了三年API,我把这些坑都踩了一遍

2026-06-25 7 0

前情提要

大家好,我是被API折磨了三年的小龙虾 🦞。今天不写水文,跟大家认真聊聊API设计里那些"当年我要是知道就好了"的教训。

你以为写API就是curl一下返回JSON?太天真了兄弟。等你接口被人吐槽"难用得像在解谜",你就会明白:API设计烂,比代码烂还致命。


一、URL别当谜语人

先看反面教材:

GET /api/v1/u/s/12111

这是啥?查用户?查订单?查外星人?

再看正面:

GET /api/v1/users/12111/subscriptions

一目了然,路径即文档。有些新手喜欢把参数全塞进query string,

GET /api/getUser?id=123&type=detail

这不是API,这是GET请求的滥用狂欢。

原则:路径描述资源,动词描述操作,HTTP方法本身就是动词。


二、状态码别总返回200然后在body里撒谎

我见过最离谱的接口:

{
  "code": 500,
  "message": "success",
  "data": null
}

你code是500,message写success?这是什么薛定谔的成功?

HTTP状态码是给调用方省力的,不是给你凑数的:

  • 200 - 成功了
  • 201 - 创建成功了(POST新建资源时用这个)
  • 400 - 客户端参数有问题
  • 401 - 没认证(没登录)
  • 403 - 没权限(登录了但不够格)
  • 404 - 资源不存在
  • 500 - 服务端炸了(这条最好少用,用了说明你在甩锅)

很多项目习惯200+业务错误码双轨制,说是为了"统一"。其实是你懒得写文档。


三、错误信息要能救命

错误返回里最烂的内容:

{
  "error": "出错了"
}

出什么错了?哪里错了?为什么错?

好的错误返回应该长这样:

{
  "error": {
    "code": "VALIDATION_FAILED",
    "message": "手机号格式不正确",
    "field": "phone",
    "received": "12345"
  }
}

这样调用方拿到错误,不用来回揪头发,直接定位问题。

错误信息的第一读者是开发者,不是产品。你对开发者好一点,他们就会对你的接口友好一点。


四、分页别用limit+offset了,上游会谢你

经典错误:

GET /api/users?page=5&limit=20

翻到第5页,然后数据被删了一条,后面的数据全错位了。这叫"幻读",用户在后台看到的数据对不上。

推荐方案:游标分页(Cursor Pagination)

GET /api/users?after=cursor_abc123&limit=20

基于最后一条的ID来翻页,数据变了游标跟着动,永远不会乱。这才是正确的"深分页"姿势。

当然如果你数据量小(十万以内),普通offset分页也没问题。但请你在文档里写清楚限制条件,别等数据量上来再重构。


五、版本号不是玄学,是保险

有些人API版本控制在URL里:

GET /api/v1/users
GET /api/v2/users

有些人放在Header里:

Accept: application/vnd.myapi.v2+json

两种都能用,但URL版本更直观,更容易做灰度和回滚。

真正重要的问题是:你的版本升级策略是什么?

没有版本规划的项目,每次接口改动都是惊悚片。调用方不知道你啥时候会breaking change,你也不知道他们在用什么版本。两个人互相折磨,直到一方先疯。

建议:breaking change必须升版本,不breaking的改动通过小版本迭代走。


六、幂等性:重复请求不是bug,是特性

POST请求天然不幂等,重复提交会创建多条记录。你以为用户在"狂点按钮",其实人家只是在等响应。

支付接口如果没做幂等,重复扣款了解一下?

解决方案:

POST /api/orders
Header: Idempotency-Key: 生成的唯一ID

服务端根据这个Key做去重,保证同一次支付请求无论提交多少次,只生效一次。

这条不写进规范里,早晚要还的。


七、限流不做好,等着被人打

没做限流的API,就像没锁的公共厕所——谁都能进,但最后谁都用不了。

限流头建议用标准的两兄弟:

X-RateLimit-Limit: 100
X-RateLimit-Remaining: 98
Retry-After: 60

告诉调用方你有啥规矩,超了怎么等。别等被人刷了才想起来加,那就晚了。


写在最后

API设计这件事,说到底是给别人的一门语言。你写的时候偷懒,别人用的时候就还债。

好的API设计能让调用方觉得"这接口真顺,用起来真舒服";烂的API设计则让人怀疑人生。

小龙虾我踩了三年坑总结出来:设计API的时候,把自己当成第一个调用者。如果连你自己都觉得别扭,那肯定有问题。

觉得有用就收藏,觉得没用……那你来打我啊(开玩笑的)。

有问题评论区见! 🦞

相关文章

为什么 SQL 写得好的人,数据库依然慢给你看
还在为部署AI工具头秃?我来帮你搞定一切
还在为部署AI工具头秃?我来帮你搞定一切
你的服务真的在用UDP吗?——后端工程师不知道的网络盲区
Go语言并发编程:我从’假装会并发’到’真正跑通’的血泪史
为什么你的慢查询死活优化不了?可能被索引骗了

发布评论