答案:使用Go标准库net和sync实现并发安全的多用户聊天系统,通过TCP连接、goroutine处理读写、sync.RWMutex保护客户端map,支持消息广播、昵称设置与退出命令。

用 Go 实现一个简易多用户聊天系统,核心在于并发安全的连接管理、实时消息广播和轻量级协议设计。不需要复杂框架,标准库 net 和 sync 就够用。
使用 TCP 服务端 + 客户端模型
Go 的 net.Listen 和 conn.Read/Write 足以支撑基础通信。每个客户端连接启动一个 goroutine 处理读写,避免阻塞其他用户。
- 服务端监听固定端口(如
:8080),Accept()后为每个连接启动handleConn() - 客户端用
net.Dial连接,发送纯文本消息(如"hello"),换行符\n作分隔 - 避免直接用
fmt.Scanln读输入——它会阻塞;改用bufio.NewReader(os.Stdin).ReadString('\n')
用 map + sync.RWMutex 管理在线用户
不能直接用普通 map 存连接,因为多个 goroutine 并发读写会 panic。加读写锁是最简单可靠的方案。
- 定义全局变量:
var clients = make(map[*net.Conn]bool)+var mu sync.RWMutex - 新连接加入时:
mu.Lock(); clients[&conn] = true; mu.Unlock() - 广播消息前:
mu.RLock(); defer mu.RUnlock(),遍历只读不修改 - 连接断开时记得从 map 中删掉,并关闭 conn
实现消息广播:遍历所有活跃连接并写入
广播不是“发一次给服务器,服务器转发”,而是服务端主动把消息 copy 到每个 client conn。关键点是处理写失败(如客户端已断开)。
立即学习“go语言免费学习笔记(深入)”;
- 对每个 client conn 调用
conn.Write([]byte(msg)) - 如果返回 error(如
io.EOF或broken pipe),说明连接已失效,应删掉该 conn 并关闭它 - 建议每条广播前加时间戳和发送者标识,例如:
[14:22:05][Alice] Hi there! - 不要在广播循环里做耗时操作(如日志写磁盘),否则拖慢整体响应
支持简单命令与用户昵称
提升可用性的小技巧:让客户端能输入 /nick Bob 改名,/quit 退出,服务端识别并响应。
- 服务端收到消息后先 trim 空格,检查是否以
/开头 -
/nick xxx→ 更新该 conn 对应的用户名(可用另一个 map 记录conn → name) -
/quit→ 主动关闭 conn,清理 clients map,广播“xxx 下线了” - 普通消息则按格式广播,如
"[Alice] hello"
基本上就这些。不依赖第三方库,百行左右代码就能跑通多用户实时聊天。重点是理解并发安全的共享状态管理,以及如何优雅处理连接生命周期。后续可扩展 JSON 消息、私聊、历史回溯,但底子要稳。










