代码之家  ›  专栏  ›  技术社区  ›  CapBul

只有case子句(没有case表达式)和default case的select语句在Golang中做什么?

  •  0
  • CapBul  · 技术社区  · 2 年前

    我很难理解下面的代码摘录。run()f-n作为goroutine执行,我认为它负责将“gloabl”广播频道中的所有条目发送到相应的客户端频道(chan.send)。我在第二个select语句case子句中迷失了方向。它是否只在客户端推送消息结构。发送频道,或者这个特定的语法还有更多吗?

    func (h *Hub) run() {
        for {
            select {
            ...
            case message := <-h.broadcast:
                for client := range h.clients[someid] { //clients = make(map[int][]*Client)
                    select {
                        case client.send <- message: //???
                        default:
                            close(client.send)
                            delete(h.clients, client)
                    }
                }
            }
        }
    }
    1 回复  |  直到 2 年前
        1
  •  2
  •   icza    2 年前

    这叫做非阻塞发送。 Spec: Select statements:

    如果一个或多个通信可以继续,则通过统一的伪随机选择来选择一个可以继续的通信。 否则,如果存在默认情况,则选择该情况。 如果没有默认情况,“select”语句阻塞,直到至少一个通信可以继续。

    如果 select 声明准备好了,还有一个 default 在这种情况下,它会立即被选中,而无需等待通信运营部在未来某个时间做好准备。

    有问题的代码试图在客户端的通道上发送消息,如果没有准备好,客户端将立即被丢弃。如果发送可以继续(因为通道的缓冲区中有空间,或者有一个goroutine准备从通道接收),则执行发送操作,循环继续到下一个迭代(前进到下一个客户机)。

    这样做的目的很可能是防止慢速或死机客户端减慢甚至阻塞整个集线器。使用无条件发送操作,如 client.send <- message ,如果客户端没有准备好接收和处理消息,这将阻塞,实际上会阻塞所有其他客户端和集线器本身。