go - 由于某种原因,将值传递给通道正在阻塞线程
问题描述
我正在使用通道从 HTTP 处理程序传递消息:
package server
import (
"bytes"
"errors"
"io/ioutil"
"log"
"net/http"
)
type Server struct {}
func (s Server) Listen() chan interface{} {
ch := make(chan interface{})
http.HandleFunc("/", handle(ch))
go http.ListenAndServe(":8080", nil)
return ch
}
func handle(ch chan interface{}) func(http.ResponseWriter, *http.Request) {
return func(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "application/json")
b, err := ioutil.ReadAll(r.Body)
defer r.Body.Close()
if err != nil {
ch <- errors.New(string(500))
return
}
w.Write([]byte("Hello World"))
log.Print("about to pass to handler channel")
ch <- bytes.NewBuffer(b)
log.Print("passed to handler channel")
}
}
当我向在端口 8080 上运行的服务器发出请求时,线程在此行阻塞:
ch <- bytes.NewBuffer(b)
为什么会这样?如果你注意到了,我正在一个 goroutine 中运行监听器。我还认为 HTTP 句柄发生在一个单独的线程中。如果我删除上面的行,线程就会被解锁并且程序按预期工作。我究竟做错了什么?
为了澄清,我希望能够将 POST 请求的主体传递给通道。帮助。
更新: 我正在阅读主线程上的频道:
listenerChan := n.Listen()
go SendRequest("POST", "http://localhost:8080", []byte("hello"))
for listenedMsg := range listenerChan {
log.Print("listened message>>>> ", listenedMsg)
}
但是线程仍然阻塞在同一行。为了澄清起见,我发送请求的方式没有任何问题。如果我删除上面的通道发送线,线程不会阻塞。
解决方案
因为通道是无缓冲的,所以发送操作会阻塞,直到有人准备好接收它们。使通道缓冲只会延迟阻塞,所以你总是需要一些阅读 goroutine。
更新您的更新:程序的控制流程如下所示:
- 服务器开始监听
main
发送请求并等待响应- 服务器收到请求并尝试写入通道
main
从通道读取
4 可能只发生在 2 之后,它被 3 阻止,因为 4 还没有发生。经典的僵局。
推荐阅读
- servicenow - 在Servicenow中发送电子邮件时,业务规则将“收件人”和“抄送”剪切为“密件抄送”
- php - 尝试在 Laravel 5.8 中上传图像数组时仅上传最后一张图像
- python - python中的时间模块不测量两行之间的时间差,总是显示0
- javascript - 如何在 Discord.RichEmbed() 中显示或使用变量
- android - 通知未按预期触发
- android - 如何在辅助功能服务中捕捉长按返回按钮?
- java-8 - 通过 JCodec 或类似方法将 Java 8 BufferedImages 转换为 MP4
- prisma - Botium Box CE 游乐场访问权限?
- javascript - laravel(vuejs 和 vuex)在 callResetPassword 中函数的参数太多
- html - 中心内容 - 然后与 Bootstrap 4 左对齐