首页 > 解决方案 > 由于某种原因,将值传递给通道正在阻塞线程

问题描述

我正在使用通道从 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)
}

但是线程仍然阻塞在同一行。为了澄清起见,我发送请求的方式没有任何问题。如果我删除上面的通道发送线,线程不会阻塞。

标签: go

解决方案


因为通道是无缓冲的,所以发送操作会阻塞,直到有人准备好接收它们。使通道缓冲只会延迟阻塞,所以你总是需要一些阅读 goroutine。

更新您的更新:程序的控制流程如下所示:

  1. 服务器开始监听
  2. main发送请求并等待响应
  3. 服务器收到请求并尝试写入通道
  4. main从通道读取

4 可能只发生在 2 之后,它被 3 阻止,因为 4 还没有发生。经典的僵局。


推荐阅读