大家好,今天我将分享一个使用Go语言从零开始构建的控制台并发聊天室项目。这个项目虽然简单,但它麻雀虽小五脏俱全,非常适合用来学习和实践Go语言强大的并发特性,尤其是 goroutine
和 channel
的使用。
一、项目亮点与功能特性
这个聊天室项目完全基于Go语言标准库实现,无需任何第三方依赖。它主要包含以下功能:
-
多用户并发通信:支持多个客户端同时连接和收发消息。
- 用户上线/下线广播:当有新用户加入或离开聊天室时,系统会自动向所有在线用户广播通知 。
-
实时群组聊天:任何一个用户发送的消息都会被实时广播给所有其他在线用户 。
-
查询在线用户:用户可以随时通过输入
who
命令,获取当前所有在线用户的列表 。 -
在线改名:用户可以使用
rename|新名字
的格式,随时修改自己的昵称 。 -
超时强制T出:为了管理资源,系统会自动T出长时间未活动的非活跃用户 。
二、项目整体架构
项目的核心设计思想是“分而治之”,充分利用Go的并发能力。主协程负责监听和接受新的客户端连接,每当有新用户接入,就会为其创建一个独立的 goroutine
(HandlerConnect
) 来处理所有与该用户相关的交互。
消息处理的流程如下:
-
用户输入:各个客户端的
HandlerConnect
协程负责读取用户在终端输入的消息。 -
消息汇总:
HandlerConnect
将收到的消息写入一个全局的message
通道。 -
中央广播:一个全局唯一的
Manager
管理者协程持续监听message
通道。一旦收到消息,它会立即将该消息分发给所有在线用户的专属通道中。 -
消息写回:每个客户端还有一个专门的
WriteMsgToClient
协程,负责从自己的专属通道里读取消息,并将其最终写回到用户的终端界面上,完成消息显示。
三、核心代码解析
1. 用户结构体与全局变量
我们首先定义了用户的核心结构体 Client
,以及用于通信的全局 map
和 channel
。
// 创建用户结构体类型
type Client struct {C chan string // 用户专属的、用于接收消息的channelName string // 用户名Addr string // 用户的网络地址
}// 创建全局map 储存在线用户
var onlineMap map[string]Client// 创建全局channel 传递用户消息,充当消息总线
var message = make(chan string)
2. 管理者协程 Manager
Manager
是整个聊天室的消息中枢。它在一个死循环中不断地从全局 message
通道读取消息,然后遍历 onlineMap
,将消息并发地发送给每一个在线用户。
func Manager() {// 初始化 onlineMaponlineMap = make(map[string]Client)// 监听全局channel 中是否有数据for {msg := <-message // 无消息时会阻塞// 循环发送消息给所有在线用户for _, clnt := range onlineMap {clnt.C <- msg}}
}
3. 客户端处理协程 HandlerConnect
这是每个客户端的“管家”,也是项目中最核心的逻辑部分。它负责处理一个客户端从连接到断开的整个生命周期。
func HandlerConnect(conn net.Conn) {defer conn.Close()// ... 初始化Client并加入onlineMap ...// 启动一个专门给当前客户端写数据的go程go WriteMsgToClient(clnt, conn)// 广播用户上线message <- MakeMsg(clnt, "login")// 创建用于监听用户退出的channelisQuit := make(chan bool)// 创建用于判断用户是否活跃的channelhasData := make(chan bool)// 匿名go程,专门处理用户发送的消息go func() {buf := make([]byte, 4096)for {// ... 读取用户输入 conn.Read(buf) ...// 将读到的用户消息 写入message,或处理who/rename等命令message <- MakeMsg(clnt, msg)hasData <- true // 代表用户有活动}}()// 使用select监听各种状态for {select {case <-isQuit:// ... 处理用户退出逻辑 ...returncase <-hasData:// 此case仅用于重置下面的计时器,不做任何事case <-time.After(time.Second * 10): // 设置10秒超时// ... 处理超时T出逻辑 ...return}}
}
四、如何运行
1. 环境准备
请确保您已安装并配置好 Go 语言开发环境。
2. 获取源码
打开您的终端,使用 git
克隆项目代码。
git clone https://github.com/Joker-0111-G/Go-Concurrent-Chat-Room.git
3. 启动服务
进入项目目录,运行以下命令启动聊天室服务端。
cd Go-Concurrent-Chat-Room
go run 001ChatRoom.go
当您看到终端没有退出时,表示服务端已在 127.0.0.1:8000
端口上成功启动。
4. 连接客户端
您可以打开多个新的终端窗口,使用 telnet
或 nc
命令来模拟多个用户连接到聊天室。
telnet 127.0.0.1 8000
nc 127.0.0.1 8000
每一个成功连接的终端窗口都代表一个在线用户。
五、项目源码地址
欢迎访问项目的 GitHub 仓库,获取完整源代码,也欢迎您提出宝贵的 Issue 或 PR!
-
GitHub地址: https://github.com/Joker-0111-G/Go-Concurrent-Chat-Room.git
六、总结
通过这个简单的并发聊天室项目,我们可以非常直观地学习到 Go 语言在并发编程中的优雅和强大。goroutine
轻量级线程模型和 channel
通信机制的结合,使得编写高并发应用变得异常轻松。希望这个项目能对您学习Go语言有所帮助!