繁体   English   中英

在产生 goroutine 的函数返回之后,goroutine 发送到没有接收器的无缓冲通道会永远阻塞吗?

[英]does a goroutine sending to an unbuffered channel without receivers block forever, after the function that spawns the goroutine returns?

请考虑以下处理程序,

http.HandleFunc("/task", func(w http.ResponseWriter, r *http.Request) {
        w.Header().Set("Access-Control-Allow-Origin", *cors)
        if r.Method != http.MethodPost {
            http.Error(w, "only POST method is allowed", http.StatusMethodNotAllowed)
            return
        }
        ack := make(chan bool)
        go func() {
            time.Sleep(time.Second)
            ack <- false
        }()
        server.BroadcastToRoom(r.FormValue("alias"), "task", task{TaskID: "1"}, func() {
            ack <- true
        })
        if a := <-ack; !a {
            w.WriteHeader(http.StatusNoContent)
        } else {
            w.WriteHeader(http.StatusCreated)
        }
    })

BroadcastToRoom将回调作为参数。 在这个回调中(可能永远不会发生),我向确认通道发送了一个布尔值。 如果 1 秒后未确认,则超时。

我正在试验实现超时的方法。 我写了这个 goroutine 并且它有效。 但是,根据这个操场,goroutine 在产生它的函数返回后继续运行。

所以我认为因为 goroutine 一直在运行并试图将一个值发送到一个没有接收器的无缓冲通道,goroutine 将永远阻塞。 我想我可以通过使用大小为 1 的缓冲区来解决这个问题。

我想知道我的假设是否正确。 如果是这样,是否有比使用缓冲区大小为 1 并让它静默完成更好的方法来阻止它?

在您的场景中,goroutine 将泄漏(它将继续存在)。 如果没有人在侦听该通道,则终止 goroutine 的正确方法是使用非阻塞写入:

 go func() {
            time.Sleep(time.Second)
            select {
               case ack <- false:
               default:
            }
        }()

这样,如果超时后没有人在侦听,它将选择default ,并终止 goroutine。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM