Golang中HTTP handler卡住的解决方法
Golang中HTTP handler卡住的解决方法 以下是我的代码,它由一个在端口8002的“/api”路径上的处理器调用:
https://play.golang.org/p/xFx4DfLpjsV
处理器函数在第56行打开一个名为rubrik_locations的JSON文件,该文件包含以下测试内容:
"rubrik" : [
{
"site": {
"server": "https://postman-echo.com/get?foo1=bar1&foo2=bar2"
}
},
{
"site": {
"server": "https://postman-echo.com/get?foo1=bar1&foo2=bar2"
}
}
],
"index": 1
}
这段代码背后的思路是,每次在浏览器中传入带有主机的URL时,在一个循环中将“server”参数传递给真实的URL:
http://localhost:8002/api/test.com
我遇到的问题在于,当循环开始时,调用会卡住(加载永不停止,持续旋转),并且不会继续向下执行,也不会在我第110行的“Output”结构体中打印任何内容。在该结构体中,切片接口本应接收来自“resps”通道的结果:
output := Output{
Success: true,
Vm: slice,
LogOutput: "Returned information location for host: " + server,
}
更多关于Golang中HTTP handler卡住的解决方法的实战教程也可以访问 https://www.itying.com/category-94-b0.html
感谢您的建议。我完全忽略了那些返回语句。
更多关于Golang中HTTP handler卡住的解决方法的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html
对我来说,请求 https://postman-echo.com/get?foo1=bar1&foo2=bar2test.com 耗时超过3秒,我遇到了超时(你设置的超时时间是3秒)。
我不明白你为什么要把东西放进通道,然后在同一个goroutine里稍后读取它。
请注意,如果你不向 resps 通道发送任何内容,那么在不出错的情况下,它永远不会收到任何响应。
当发生错误时,你把错误放进了通道,但函数结束了(return),所以它永远没有机会执行。
因此,如果我这样修改代码:
resps <- "HURRA"
select {
case slice := <-resps:
fmt.Println(slice)
return
}
它就能工作了 🙂
一个小的建议——在检查错误之前就关闭响应。
if resp != nil {
defer resp.Body.Close()
}
if err != nil {
//将URL输出追加到resps通道
resps <- err
return
}
问题出在并发处理和通道通信上。你的代码中resps通道没有正确关闭,导致接收端一直等待数据,造成死锁。
以下是修复后的关键部分:
// 修改第56行后的处理逻辑
var wg sync.WaitGroup
resps := make(chan Response, len(rubrik.Rubrik))
for _, site := range rubrik.Rubrik {
wg.Add(1)
go func(s Site) {
defer wg.Done()
resp, err := http.Get(s.Server)
if err != nil {
resps <- Response{Error: err}
return
}
defer resp.Body.Close()
body, err := ioutil.ReadAll(resp.Body)
if err != nil {
resps <- Response{Error: err}
return
}
resps <- Response{Body: body}
}(site.Site)
}
// 添加goroutine来关闭通道
go func() {
wg.Wait()
close(resps)
}()
// 收集结果
var slice []interface{}
for resp := range resps {
if resp.Error != nil {
// 错误处理
continue
}
var result map[string]interface{}
if err := json.Unmarshal(resp.Body, &result); err == nil {
slice = append(slice, result)
}
}
主要修改:
- 使用
sync.WaitGroup等待所有goroutine完成 - 添加单独的goroutine在等待完成后关闭通道
- 使用带缓冲的通道避免阻塞
- 修复goroutine闭包变量捕获问题
这样处理可以确保所有HTTP请求完成后通道被正确关闭,for resp := range resps循环能够正常退出。

