英文:
What does a select statement with just a case clause (without case expression) and default case do in Golang?
问题
我有困难理解以下代码片段。run() 函数作为一个 goroutine 执行,我认为它负责将所有在 'global' 广播通道中的条目分发到相应的客户端通道(chan.send)。我在第二个 select 语句中的 case 子句中迷失了。它只是将消息结构体推送到 client.send 通道中,还是这个特定语法还有其他含义?
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)
}
}
}
}
}
英文:
I have trouble understanding the following excerpt of code. The run() f-n is executed as a goroutine and I think is responsible for dispatching all entries in the 'gloabl' broadcast channel to the corresponding client channels (chan.send). I lose track in the second select statement, in the case clause. Does it only push the message struct in the client.send channel or is there more to this specific syntax?
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
得分: 3
这被称为非阻塞发送。如果其中一个通信可以进行,将通过均匀伪随机选择选择一个可以进行的通信。否则,如果有默认情况,则选择该情况。如果没有默认情况,则“select”语句将阻塞,直到至少有一个通信可以进行。
如果“select”语句的所有通信操作都没有准备好,并且有一个“default”情况,则立即选择该情况,而不等待将来某个时间通信操作准备好。
所讨论的代码尝试在客户端的通道上发送消息,如果通道没有准备好,则立即丢弃客户端。如果发送可以进行(因为通道缓冲区中有空间或者有一个goroutine准备从通道接收),则执行发送操作,并继续循环到下一个迭代(前进到下一个客户端)。
这样做的目的很可能是防止慢速或无响应的客户端减慢甚至阻塞整个中心。如果使用无条件的发送操作,如client.send <- message
,如果客户端没有准备好接收和处理消息,这将导致阻塞,从而阻塞所有其他客户端和中心本身。
英文:
It's called non-blocking send. Spec: Select statements:
> If one or more of the communications can proceed, a single one that can proceed is chosen via a uniform pseudo-random selection. Otherwise, if there is a default case, that case is chosen. If there is no default case, the "select" statement blocks until at least one of the communications can proceed.
If none of the communication ops of the select
statement are ready, and there is a default
case, it is chosen immediately without waiting for the comm. ops to become ready some time in the future.
The code in question tries to send a message on the client's channel, and if it's not ready, the client is dropped immediately. If the send can proceed (because there's room in the channel's buffer or there's a goroutine ready to receive from the channel), the send operation is carried out, and the loop goes on to the next iteration (advances to the next client).
The intention is likely to prevent slow or dead clients to slow down or even block the entire hub. Using an unconditional send operation like client.send <- message
, if the client is not ready to receive and process the message, this would block, essentially blocking all other clients and the hub itself.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论