在 Go 中使用 select 发送到频道有什么好处?

在 Gorilla websocket 的示例目录中有一个名为 hub.go 的文件。


https://github.com/gorilla/websocket/blob/master/examples/chat/hub.go


在这里,您可以在类型集线器上找到执行此操作的方法。


func (h *hub) run() {

    for {

        select {

        case c := <-h.register:

            h.connections[c] = true

        case c := <-h.unregister:

            if _, ok := h.connections[c]; ok {

                delete(h.connections, c)

                close(c.send)

            }

        case m := <-h.broadcast:

            for c := range h.connections {

                select {

                case c.send <- m:

                default:

                    close(c.send)

                    delete(h.connections, c)

                }

            }

        }

    }

}

为什么在最后一种情况下它不直接发送到 c.send 通道?


case m := <-h.broadcast:

    for c := range h.connections {

        c.send <- m

    }


慕丝7291255
浏览 171回答 2
2回答

撒科打诨

它是保证非阻塞发送到通道的方法。如果 c.send chan 现在不能接受新消息,将执行一个默认分支。如果没有 select{} 块发送到未缓冲或完全填充的缓冲通道,则可以被阻止。

慕的地8271018

https://gobyexample.com/non-blocking-channel-operations// Basic sends and receives on channels are blocking.// However, we can use `select` with a `default` clause to// implement _non-blocking_ sends, receives, and even// non-blocking multi-way `select`s.package mainimport "fmt"func main() {&nbsp; &nbsp; messages := make(chan string)&nbsp; &nbsp; //[...]&nbsp; &nbsp; // Here's a non-blocking receive. If a value is&nbsp; &nbsp; // available on `messages` then `select` will take&nbsp; &nbsp; // the `<-messages` `case` with that value. If not&nbsp; &nbsp; // it will immediately take the `default` case.&nbsp; &nbsp; select {&nbsp; &nbsp; case msg := <-messages:&nbsp; &nbsp; &nbsp; &nbsp; fmt.Println("received message", msg)&nbsp; &nbsp; default:&nbsp; &nbsp; &nbsp; &nbsp; fmt.Println("no message received")&nbsp; &nbsp; }&nbsp; &nbsp; // A non-blocking send works similarly.&nbsp; &nbsp; msg := "hi"&nbsp; &nbsp; select {&nbsp; &nbsp; case messages <- msg:&nbsp; &nbsp; &nbsp; &nbsp; fmt.Println("sent message", msg)&nbsp; &nbsp; default:&nbsp; &nbsp; &nbsp; &nbsp; fmt.Println("no message sent")&nbsp; &nbsp; }&nbsp; &nbsp; //[...]}更明确地说:对于非阻塞“发送”,case如果有接收者已经在等待消息,则第一个将发生。否则它会回落到default
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Go