1.在响应HTTP请求后忘记加 return 语句
在编写HTTP处理程序时,很容易在响应HTTP请求后忘记加 return 语句。这可能会导致一种奇怪的情况,即应该在发生错误后停止处理程序,但我们没有这样做。
可以在下面的例子中观察到这种情况:
func handler(w http.ResponseWriter, req *http.Request) {
err := foo(req)
if err != nil {
http.Error(w, "foo", http.StatusInternalServerError)
}
/ ...
}
如果foo返回错误,我们用 http.Error 来处理它,http.Error 用 foo 的错误消息和错误码为500的服务器内部错误来响应请求。这段代码的问题在于,如果进入 if err != nil 分支,应用程序将继续执行,因为http.Error不会停止执行处理程序。
这种错误的真正影响是什么呢? 首先,让我们在 HTTP 方面讨论它。假设我们已经通过添加一个步骤来编写成功的 HTTP 响应体和状态代码完成了前面的HTTP处理程序:
func handler(w http.ResponseWriter, req *http.Request) {
err := foo(req)
if err != nil {
http.Error(w, "foo", http.StatusInternalServerError)
}
_, _ = w.Write([]byte("all good"))
w.WriteHeader(http.StatusCreated)
}
在 err != nil 的情况下,HTTP 响应如下:
foo
all good
这段响应中既有失败的信息也有成功的信息。
我们将只返回第一个 HTTP 状态码:在前面的示例中,是 500 。然而,Go 也会记录一个警告:
2024/04/14 14:48:33 http: superfluous response.WriteHeader call
from main.handler (main.go:20)
这个警告意味着,我们尝试多次写入状态码,但这样做是多余的。
在代码执行方面,主要影响是将会继续执行本应停止的函数。例如,如果 foo 在错误之外还返回一个指针,那么继续执行将会使用这个指针,可能会导致 nil 指针废弃(因此会出现