简单 HTTP 服务器中的多个 WriteHeader 调用
使用 net/http 包在 Go 中实现的基本 HTTP 服务器表现出异常行为,如错误消息指示:
http: multiple response.WriteHeader calls
此错误表明服务器正在尝试将响应标头写入多个次,这是 HTTP 规范不允许的。让我们分析代码以了解出现此问题的原因:
func main() { http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { fmt.Println(r.URL) go HandleIndex(w, r) }) fmt.Println("Starting Server...") log.Fatal(http.ListenAndServe(":5678", nil)) } func HandleIndex(w http.ResponseWriter, r *http.Request) { w.WriteHeader(200) w.Write([]byte("Hello, World!")) }
分析
主要问题在于注册为传入请求处理程序的匿名函数:
func(w http.ResponseWriter, r *http.Request) { fmt.Println(r.URL) go HandleIndex(w, r) }
该函数打印请求 URL 并启动一个新的 goroutine 来调用 HandleIndex()。然后,它继续正常执行。
如果处理函数没有设置响应状态或向响应写入任何内容,Go 会自动将状态设置为 200(HTTP OK)并返回。此行为适用于我们代码中的匿名函数,该函数不会显式设置响应状态或在 go HandleIndex(w, r) 行之前写入响应状态。
当在单独的代码中调用 HandleIndex() 时goroutine 中,匿名函数继续执行,以请求处理结束。由于事先没有设置响应状态,Go 会自动将其设置为 200 HTTP OK。然而,生成的 goroutine 也会尝试在 HandleIndex() 中设置响应状态,从而导致“多次 response.WriteHeader 调用”错误。
解决方案
至避免此问题,可以从启动 goroutine 的行中删除“go”关键字:
func(w http.ResponseWriter, r *http.Request) { fmt.Println(r.URL) HandleIndex(w, r) }
或者确保匿名函数设置响应状态并在返回之前写入:
func(w http.ResponseWriter, r *http.Request) { fmt.Println(r.URL) w.Write([]byte("Hello, World!")) go HandleIndex(w, r) }
以上是为什么我的 Go HTTP 服务器中会出现'http:多重响应.WriteHeader 调用”错误?的详细内容。更多信息请关注PHP中文网其他相关文章!