Go 多余的写头和无响应
我正在编写一个向WebSocket网关发送请求的HTTP API。我使用的是Go 多余的写头和无响应,go,gorilla,go-http,Go,Gorilla,Go Http,我正在编写一个向WebSocket网关发送请求的HTTP API。我使用的是go1.14.7和gorilla/muxv1.8.0。代码将使用GOOS=linuxGOARCH=armGOARM=7进行交叉编译 我的问题如下: respondBadRequest()始终记录此操作,即使我从未使用WriteHeader: http:多余的response.WriteHeader调用来自main。(*HttpHandler)。respondBadRequest 即使调用了respondBadRe
go1.14.7
和gorilla/mux
v1.8.0
。代码将使用GOOS=linux
GOARCH=arm
GOARM=7
进行交叉编译
我的问题如下:
始终记录此操作,即使我从未使用respondBadRequest()
:WriteHeader
http:多余的response.WriteHeader调用来自main。(*HttpHandler)。respondBadRequest
- 即使调用了
,API响应始终是respondBadRequest()
200OK
- API响应总是有一个空的主体
类型HttpHandler结构{
网关
}
func(h*HttpHandler)respondSuccess(w http.ResponseWriter,文本字符串){
w、 写入([]字节(文本))
}
func(h*HttpHandler)respondBadRequest(w http.ResponseWriter,文本字符串){
http.Error(w,text,http.StatusBadRequest)
}
func(h*HttpHandler)响应错误(w http.ResponseWriter,文本字符串){
http.Error(w,text,http.StatusInternalServerError)
}
func(h*HttpHandler)OnFoobar(w http.ResponseWriter,r*http.Request){
f:=func(成功布尔,e错误){
如果e!=nil{
h、 响应错误(w,e.Error())
}否则,如果成功的话{
h、 响应成功(w,“Foobar接受”)
}否则{
h、 respondBadRequest(w,“未知Foobar”)
}
}
//...
e:=h.gateway.Foobar(f)
如果e!=nil{
log.Println(e)
}
}
//...
httpHandler:=&httpHandler{
网关:网关,
}
r:=mux.NewRouter()
r、 HandleFunc(“/foobar”,httpHandler.OnFoobar)
http.listendServe(“:8000”,r)
正如@mkopriva指出的,f
显然是在OnFoobar
已经完成并编写了一个隐式空响应之后调用的。使用sync.WaitGroup
修复His:
foobar上的func(h*HttpHandler)(w http.ResponseWriter,r*http.Request){
wg:=新建(sync.WaitGroup)
工作组.添加(1)
f:=func(成功布尔,e错误){
如果e!=nil{
h、 响应错误(w,e.Error())
}否则,如果成功的话{
h、 响应成功(w,“Foobar接受”)
}否则{
h、 respondBadRequest(w,“未知Foobar”)
}
wg.Done()
}
//...
e:=h.gateway.Foobar(f)
如果e!=nil{
log.Println(e)
}
wg.Wait()
}
如果编写响应的任何部分,则已调用
WriteHeader
。在已经编写响应之后,您不能发送其他标头。您不是直接调用WriteHeader
,而是在多个地方间接调用它;如果您调用Write
且尚未调用WriteHeader
,Write
将调用WriteHeader(200)
(如文档中所述)http.Error
还调用WriteHeader
。如果您希望以错误进行响应,则必须在调用Write
发送任何正文内容之前执行此操作(在HTTP响应中,状态和标题必须位于响应正文之前)。f
看起来像一个回调,所以我想Foobar
是异步的吗?它是不是在一个社交场合做它的工作?如果处理程序OnFoobar
没有等待Foobar
完成,当它退出时,如果w
尚未写入,Go的serve mux将默认写入200ok,然后,当Foobar
完成并调用回调时,您会得到您得到的错误。@Steffen在这种情况下,使用sync.WaitGroup
@Steffen这样做应该可以,我相信:在OnFoobar返回后调用f并不明显,因为Go中的最佳实践是提供同步api。