多个response.WriteHeader调用真的很简单的例子? [英] multiple response.WriteHeader calls in really simple example?

查看:119
本文介绍了多个response.WriteHeader调用真的很简单的例子?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我使用了最基本的net / http程序来学习Go中的命名空间:

  package main 


$ f
$ log
$ net $ http

$ b func main() {
http.HandleFunc(/,func(w http.ResponseWriter,r * http.Request){
fmt.Println(r.URL)
go HandInIndex(w,r)
$)

fmt.Println(Starting Server ...)
log.Fatal(http.ListenAndServe(:5678,nil))
}
$ b $ func HandleIndex(w http.ResponseWriter,r * http.Request){
w.WriteHeader(200)
w.Write([] byte(Hello,World !))
}

当我运行程序并连接到 localhost:5678 在Chrome中,我在控制台中得到这个:

 启动服务器.. 。
/
2015/01/15 13:41:29 http:multiple response.WriteHeader calls
/favicon.ico
2015/01/15 13:41:29 http :multiple response.WriteHeader调用

但我不明白这是可能的。我打印URL,启动一个新的goroutine,写一次头文件,并给它一个 Hello,World!的静态正文。好像有两件事情中的一件发生了。无论是幕后的内容是编写另一个头文件,还是以某种方式为同一个请求调用两次 HandleIndex 。我可以做什么来停止编写多个头文件?

编辑:这似乎与有关> go HandleIndex(w,r)行,因为如果我删除 go 并且只是将它作为一个函数调用而不是goroutine,我不会收到任何问题,并且浏览器获取它的数据。由于它是一个goroutine,我得到了多个WriteHeader错误,并且浏览器不显示Hello World。为什么这是一个goroutine破坏它?

解决方案

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

  func(w http.ResponseWriter,r * http.Request){
fmt.Println(r.URL)
go HandleIndex(w,r)
}

到标准输出),然后在新的goroutine中调用 HandleIndex()并继续执行。



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



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



所以如果你在一个新的goroutine中调用 HandleIndex ,你的原始匿名函数将会继续:它会结束并响应头部被设置 - 同时(同时)您启动的新goroutine也会设置响应头 - 因此multiple response.WriteHeader调用错误。



如果你删除了go,你的 HandleIndex 函数会在响应头部之前设置相同的goroutine你的处理函数返回,而net / http会知道这个,并且不会再尝试设置响应头,所以你遇到的错误不会发生。


I have the most basic net/http program that I'm using to learn the namespace in Go:

package main

import (
    "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!"))
}

When I run the program and connect to localhost:5678 in Chrome, I get this in the console:

Starting Server...
/
2015/01/15 13:41:29 http: multiple response.WriteHeader calls
/favicon.ico
2015/01/15 13:41:29 http: multiple response.WriteHeader calls

But I don't see how that's possible. I print the URL, start up a new goroutine, write the header once, and give it a static body of Hello, World! It seems like one of two things is happening. Either something behind the scenes is writing another header or somehow HandleIndex is called twice for the same request. What can I do to stop writing multiple headers?

EDIT: It seems to have something to do with the go HandleIndex(w, r) line because if I remove go and just make it a function call instead of a goroutine, I don't get any issues and the browser gets it's data. With it being a goroutine, I get the multiple WriteHeader error and the browser doesn't show "Hello World." Why is making this a goroutine breaking it?

解决方案

Take a look at the anonymous function you register as the handler of incoming requests:

func(w http.ResponseWriter, r *http.Request) {
    fmt.Println(r.URL)
    go HandleIndex(w, r)
}

It prints the URL (to the standard output) then calls HandleIndex() in a new goroutine and continues execution.

If you have a handler function where you do not set the response status before the first call to Write, Go will automatically set the response status to 200 (HTTP OK). If the handler function does not write anything to the response (and does not set the response status and completes normally), that is also treated as a successful handling of the request and the response status 200 will be sent back. Your anonymous function does not set it, it does not even write anything to the response. So Go will do just that: set the response status to 200 HTTP OK.

Note that handling each request runs in its own goroutine.

So if you call HandleIndex in a new goroutine, your original anonymous function will continue: it will end and so the response header will be set - meanwhile (concurrently) your started new goroutine will also set the response header - hence the "multiple response.WriteHeader calls" error.

If you remove the "go", your HandleIndex function will set the response header in the same goroutine before your handler function returns, and the "net/http" will know about this and will not try to set the response header again, so the error you experienced will not happen.

这篇关于多个response.WriteHeader调用真的很简单的例子?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆