
本文详解 rest api 中 get 请求应如何正确使用 http 状态码:200 表示成功返回(含空数组),404 仅用于资源路径根本不存在,500 用于不可恢复的服务器内部错误(如 json 序列化失败)。
本文详解 rest api 中 get 请求应如何正确使用 http 状态码:200 表示成功返回(含空数组),404 仅用于资源路径根本不存在,500 用于不可恢复的服务器内部错误(如 json 序列化失败)。
在 RESTful API 设计中,HTTP 状态码不仅是技术响应,更是语义契约——它向客户端明确传达“发生了什么”,而非“代码是否运行了”。以 GET /cities 为例,常见误区是将空数据集等同于“资源不存在”,从而错误返回 404 Not Found。实际上,资源路径 /cities 所代表的集合资源是真实存在的,无论当前是否包含元素。类比数据库查询 SELECT * FROM cities WHERE 1=0,结果为空并不意味着表 cities 不存在;同理,空城市列表应返回 200 OK + [],语义清晰且利于客户端统一处理。
以下是修正后的健壮实现:
func FindCitiesHandler(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "application/json; charset=UTF-8")
// 情况1 & 2:无论 cities 非空或为空,均视为有效响应
if err := json.NewEncoder(w).Encode(cities); err != nil {
// 情况3:JSON 编码失败属于服务端不可恢复错误(如 writer 已关闭、内存不足)
http.Error(w, "Internal server error", http.StatusInternalServerError)
return
}
// 注意:无需手动调用 w.WriteHeader(200)
// json.Encoder.Write 已隐式触发 200(因 Header 尚未写入且无显式状态码)
}关键要点说明:
- ✅ 200 OK 是默认且正确的成功状态:只要请求路径合法、业务逻辑执行完成(无论结果为空或非空),就应回复
200。客户端可通过解析响应体判断数据是否存在,而非依赖状态码。 - ❌ 避免对空集合返回 404:
404 Not Found仅适用于请求的 资源标识符本身无效,例如GET /city/999(ID 999 的城市不存在)或GET /citie(路径拼写错误)。而GET /cities是一个集合端点,其存在性不依赖于当前数据量。 - ⚠️ 500 Internal Server Error 用于真正的异常:JSON 编码失败(如
io.ErrClosedPipe)、数据库连接中断、磁盘满等底层故障,应返回500并记录详细日志(切勿暴露敏感信息给客户端)。注意:http.Error()会自动设置状态码并写入错误消息,无需额外WriteHeader。 - ? 状态码设置时机需谨慎:Go 的
http.ResponseWriter在首次写入响应体(如json.Encoder.Encode)时若未设置状态码,则默认为200。因此,不应在Encode后再调用w.WriteHeader(200),否则可能触发http: superfluous response.WriteHeader警告。
总结:REST 状态码的设计核心是语义一致性。用 200 表达“我理解你的请求,并按约定格式给出了完整响应”;用 404 表达“你找的这个东西(路径/ID)在我这里压根没有定义”;用 500 表达“我的系统出问题了,不是你的错,但我现在没法给你正确答案”。坚持这一原则,API 将更可靠、更易被消费和调试。

















