广播消息
向多个客户端发送消息
广播消息 是 CoddyKit 上的免费 Go Academy 课时。 这是第 3 节课,共 4 节。 你可以在下方免费阅读本课时的完整内容 — 然后在浏览器中使用内置代码编辑器和全天候 AI 导师进行实践。 这是 Go Academy 学习路径的一部分,你的进度在网页和 CoddyKit 应用中同步。 Go Academy 课程共包含 4 节课。
向多个客户端发送消息
聊天室和实时信息流需要将一条消息推送给每个已连接的客户端。由于每个 WebSocket 只能有一个写入器,因此您需要一种协调模式:中心。
中心模式
中心是一个负责管理客户端集合和广播通道的中央协程。客户端进行注册和注销,中心将消息分发给所有客户端。没有多个协程会直接访问共享映射。
中心数据结构
中心包含:
- 一个客户端集合(
map[*Client]bool) - 一个传递消息的
broadcast通道 register和unregister通道
type Hub struct {
clients map[*Client]bool
broadcast chan []byte
register chan *Client
unregister chan *Client
}中心运行循环
单个 Run 协程通过 select 处理各个通道。由于只有这个协程会修改映射,因此不需要互斥锁。
func (h *Hub) Run() {
for {
select {
case c := <-h.register:
h.clients[c] = true
case c := <-h.unregister:
delete(h.clients, c)
close(c.send)
case msg := <-h.broadcast:
for c := range h.clients {
c.send <- msg
}
}
}
}每个客户端的发送通道
每个客户端都有一个带缓冲的 send chan []byte。中心向其中写入消息,专用写入协程从中取出消息并写入套接字。这遵守了一个写入器的规则。
type Client struct {
conn *websocket.Conn
send chan []byte
}写入协程
每个客户端都会运行一个 writePump,从 send 中依次取出消息并写入套接字。如果通道关闭,它就会发送关闭帧。
func (c *Client) writePump() {
for msg := range c.send {
c.conn.WriteMessage(websocket.TextMessage, msg)
}
}避免慢客户端
如果某个客户端速度很慢,其带缓冲的 send 通道就会被填满。一种常见策略是:缓冲区已满时移除该客户端,而不是阻塞整个中心。
select {
case c.send <- msg:
default:
close(c.send)
delete(h.clients, c)
}为什么使用通道而不是互斥锁
Go 的格言是:“通过通信来共享内存。”通过通道让一个协程统一处理所有修改,可以避免客户端映射上的竞态条件,而无需显式加锁。
广播消息
任何处理函数都可以向中心通道发送消息来进行广播;中心会将消息分发给每个已注册的客户端。
hub.broadcast <- []byte("server announcement")定向发送与广播
对于聊天室或私信,请按房间或用户 ID 保存客户端,并且只遍历相关子集,而不是所有客户端。这样即使聊天包含许多房间,也能保持高效。
可运行示例:使用通道进行分发
这个自包含程序仅使用标准库和协程,模拟中心将一条消息分发到多个客户端通道。
package main
import (
"fmt"
"sync"
)
func main() {
clients := []chan string{make(chan string, 1), make(chan string, 1), make(chan string, 1)}
msg := "hello all"
for _, c := range clients {
c <- msg // fan-out
}
var wg sync.WaitGroup
for i, c := range clients {
wg.Add(1)
go func(id int, ch chan string) {
defer wg.Done()
fmt.Printf("client %d got: %s\n", id, <-ch)
}(i, c)
}
wg.Wait()
}快速检查
请测试您对广播的理解。
回顾
您学会了向多个客户端广播:
- 中心协程负责管理客户端集合和广播通道
- 每个客户端都有一个由写入协程取出消息的带缓冲发送通道
- 这遵守了每个连接只能有一个写入器的规则
- 移除慢客户端,使中心保持响应
用 AI 导师学习 Go — 免费
在浏览器中编写并运行真实代码,获得全天候 AI 导师的即时帮助,并在网页或应用中继续学习。
- 课程
- 51
- 课程
- 203
常见问题解答
「广播消息」课时是免费的吗?
是的 — 「广播消息」的完整文本可在网页上免费阅读。要进行交互式练习(内置代码编辑器和全天候 AI 导师)并解锁 Go Academy 课程的其余内容,请升级到 CoddyKit PRO。 Go Academy 课程共包含 4 节课。
「广播消息」这节课中我会学到什么?
向多个客户端发送消息 你通过在浏览器中直接运行的动手代码来练习 Go Academy,全天候 AI 导师会在你学习这节课的过程中回答你的问题。
学习 Go Academy 需要有经验吗?
无需任何先前经验。CoddyKit 上的 Go Academy 课程适合初学者到高级学习者,你可以从这里开始或从头开始,按照自己的节奏学习。 这是第 3 节课,共 4 节。
「广播消息」课时需要多长时间?
大多数 CoddyKit 课程大约需要 5–10 分钟。每节课都很精短且互动,所以你能稳步进步,并在网页和应用中从离开的地方继续。
我能在这节 Go Academy 课中编写并运行代码吗?
能。每节 Go Academy 课都包含内置代码编辑器,你可以在浏览器中直接编写并运行真实代码,并获得即时 AI 反馈 — 无需本地设置。