【发布时间】:2019-03-21 19:24:16
【问题描述】:
我有以下 HTTP 处理函数:
func (h *UptimeHttpHandler) CreateSchedule(w http.ResponseWriter, r *http.Request) {
defer r.Body.Close()
dec := json.NewDecoder(r.Body)
var req ScheduleRequest
if err := dec.Decode(&req); err != nil {
// error handling omited
}
result, err := saveToDb(req)
if err != nil {
// error handling omited
}
// Responding with 201-Created instead of default 200-Ok
w.WriteHeader(http.StatusCreated)
enc := json.NewEncoder(w)
if err := enc.Encode(result); err != nil {
// this will have no effect as the status is already set before
w.WriteHeader(http.StatusInternalServerError)
fmt.Fprintf(w, "%v", err)
}
}
上面的代码做了以下事情:
- 请求以 JSON 数据形式出现。解码为
req - 请求被持久化在数据库中。这将返回一个结果对象,该对象将作为响应
现在在这里,一旦数据库插入成功,我们将状态码设置为201。然后使用 JSON 编码器将 JSON 编码值直接流式传输到 ResponseWriter。
当encode返回错误时,我需要将状态码更改为500。但目前我不能这样做,因为 Go 只允许设置一次状态码。
我可以通过将编码后的 JSON 保存在内存中来处理这个问题,并仅在成功时设置状态码。但这会产生不需要的副本,而且不是很好。
有没有更好的方法来处理这个问题?
【问题讨论】:
-
仅供参考,您不需要关闭 server 请求的主体,仅当您使用 client 获取请求对象时。请参阅本文档的最后一段:golang.org/pkg/net/http/#Request.Body
-
没有办法延迟写入,但是编码器返回错误的情况非常有限并且有记录,如果您的对象很大并且不缓冲 json 很重要,那么只需在这种情况下记录错误并返回一些理智的东西。由你决定哪个更重要......