为了账号安全,请及时绑定邮箱和手机立即绑定

多个 response.WriteHeader 在非常简单的例子中调用?

多个 response.WriteHeader 在非常简单的例子中调用?

Go
梦里花落0921 2021-09-10 21:18:34
我有最基本的 net/http 程序,我用它来学习 Go 中的命名空间:package mainimport (    "fmt"    "log"    "net/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!"))}当我运行程序并localhost:5678在 Chrome 中连接时,我在控制台中得到了这个:Starting Server.../2015/01/15 13:41:29 http: multiple response.WriteHeader calls/favicon.ico2015/01/15 13:41:29 http: multiple response.WriteHeader calls但我不明白这怎么可能。我打印了URL,启动一个新的goroutine,一旦写了标题,并给它一个静态的身体Hello, World!好像一两件事情正在发生。幕后的某些东西正在编写另一个标头,或者以某种方式HandleIndex为同一请求调用两次。我该怎么做才能停止编写多个标题?编辑:它似乎与该go HandleIndex(w, r)行有关,因为如果我删除go并使其成为函数调用而不是 goroutine,我不会遇到任何问题并且浏览器会获取它的数据。由于它是一个 goroutine,我收到多个 WriteHeader 错误并且浏览器不显示“Hello World”。为什么让它成为一个 goroutine 破坏它?
查看完整描述

3 回答

?
慕后森

TA贡献1802条经验 获得超5个赞

看一下您注册为传入请求处理程序的匿名函数:


func(w http.ResponseWriter, r *http.Request) {

    fmt.Println(r.URL)

    go HandleIndex(w, r)

}

它打印 URL(到标准输出),然后调用HandleIndex()一个新的 goroutine 并继续执行。


如果你有一个处理函数,你在第一次调用之前没有设置响应状态Write,Go 会自动将响应状态设置为 200(HTTP OK)。如果处理函数没有向响应写入任何内容(并且没有设置响应状态并正常完成),也被视为成功处理请求,并且响应状态 200 将被发送回。您的匿名函数没有设置它,它甚至没有向响应写入任何内容。所以 Go 会这样做:将响应状态设置为 200 HTTP OK。


请注意,处理每个请求都在其自己的 goroutine 中运行。


因此,如果您调用HandleIndex新的 goroutine,您的原始匿名函数将继续:它将结束,因此将设置响应标头 - 同时(同时)您启动的新 goroutine 也将设置响应标头 - 因此出现"multiple response.WriteHeader calls"错误。


如果您删除"go",您的HandleIndex函数将在您的处理程序函数返回之前在同一个 goroutine 中设置响应头,并且“net/http”将知道这一点并且不会再次尝试设置响应头,因此您遇到的错误将不会发生。


查看完整回答
反对 回复 2021-09-10
?
红颜莎娜

TA贡献1842条经验 获得超12个赞

您已经收到了解决您问题的正确答案,我将提供有关一般情况的一些信息(此类错误经常出现)。

文档中,您看到WriteHeader发送了一个 http 状态代码,并且您不能发送超过 1 个状态代码。如果你有Write任何东西,这相当于发送 200 状态代码然后写东西。

因此,如果您w.WriteHeader多次明确使用或使用w.Writebefore ,则会出现您看到的消息w.WriteHeader


查看完整回答
反对 回复 2021-09-10
?
Smart猫小萌

TA贡献1911条经验 获得超7个赞

从文档:


// WriteHeader sends an HTTP response header with status code. 

// If WriteHeader is not called explicitly, the first call to Write  

// will trigger an implicit WriteHeader(http.StatusOK).

在您的情况下发生的事情是您go HandleIndex从处理程序启动。第一个处理程序完成。标准 WriteHeader 写入 ResponseWriter。然后 go 例程 HandleIndex 被启动,它也尝试写一个标题并写入。


只需go从 HandleIndex 中删除它,它就会起作用。


查看完整回答
反对 回复 2021-09-10
  • 3 回答
  • 0 关注
  • 166 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信