大家好,今天我将分享一个使用Go语言从零开始构建的控制台并发聊天室项目。这个项目虽然简单,但它麻雀虽小五脏俱全,非常适合用来学习和实践Go语言强大的并发特性,尤其是 goroutinechannel 的使用。

一、项目亮点与功能特性

这个聊天室项目完全基于Go语言标准库实现,无需任何第三方依赖。它主要包含以下功能:

  • 多用户并发通信:支持多个客户端同时连接和收发消息。

  • 用户上线/下线广播:当有新用户加入或离开聊天室时,系统会自动向所有在线用户广播通知 。
  • 实时群组聊天:任何一个用户发送的消息都会被实时广播给所有其他在线用户 。

  • 查询在线用户:用户可以随时通过输入 who 命令,获取当前所有在线用户的列表 。

  • 在线改名:用户可以使用 rename|新名字 的格式,随时修改自己的昵称 。

  • 超时强制T出:为了管理资源,系统会自动T出长时间未活动的非活跃用户 。

二、项目整体架构

        项目的核心设计思想是“分而治之”,充分利用Go的并发能力。主协程负责监听和接受新的客户端连接,每当有新用户接入,就会为其创建一个独立的 goroutine (HandlerConnect) 来处理所有与该用户相关的交互。

消息处理的流程如下:

  1. 用户输入:各个客户端的 HandlerConnect 协程负责读取用户在终端输入的消息。

  2. 消息汇总HandlerConnect 将收到的消息写入一个全局的 message 通道。

  3. 中央广播:一个全局唯一的 Manager 管理者协程持续监听 message 通道。一旦收到消息,它会立即将该消息分发给所有在线用户的专属通道中。

  4. 消息写回:每个客户端还有一个专门的 WriteMsgToClient 协程,负责从自己的专属通道里读取消息,并将其最终写回到用户的终端界面上,完成消息显示。

三、核心代码解析

1. 用户结构体与全局变量

我们首先定义了用户的核心结构体 Client,以及用于通信的全局 mapchannel

// 创建用户结构体类型
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. 连接客户端

您可以打开多个新的终端窗口,使用 telnetnc 命令来模拟多个用户连接到聊天室。

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语言有所帮助!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/news/915364.shtml
繁体地址,请注明出处:http://hk.pswp.cn/news/915364.shtml
英文地址,请注明出处:http://en.pswp.cn/news/915364.shtml

如若内容造成侵权/违法违规/事实不符,请联系英文站点网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

疯狂星期四第13天运营日报

网站运营第13天&#xff0c;点击观站&#xff1a; 疯狂星期四 crazy-thursday.com 全网最全的疯狂星期四文案网站 运营报告 昨日访问量 昨天大概60个ip, 同比上个星期是高点的&#xff0c;但是与星期四差别还是太大了。&#x1f602; 昨日搜索引擎收录情况 百度依旧0收录 …

吴恩达《AI for everyone》第二周课程笔记

机器学习项目工作流程以Echo/Alexa&#xff08;语音识别AI&#xff09;作为例子解释&#xff1a; 1. collect data 收集数据——人为找很多人说 Alexa&#xff0c;并录制音频&#xff1b;并且还会让一群人说其他词语&#xff0c;比如hello 2. train model 训练模型——用机器学…

uniapp props、$ref、$emit、$parent、$child、$on

1. uniapp props、ref、ref、ref、emit、parent、parent、parent、child、$on 1.1. 父组件和子组件 propsPage.vue导入props-son-view.vue组件的时候,我们就称index.vue为父组件依次类推,在vue中只要能获取到组件的实例,那么就可以调用组件的属性或是方法进行操作 1.2. pr…

4、ubuntu | dify创建知识库 | 上市公司个股研报知识库

1、创建知识库步骤 创建一个知识库并上传相关文档主要涉及以下五个关键步骤&#xff1a; 创建知识库&#xff1a;首先&#xff0c;需要创建一个新的知识库。这可以通过上传本地文件、从在线资源导入数据或者直接创建一个空的知识库来实现。 指定分段模式&#xff1a;接下来是…

Kubernetes中为Elasticsearch配置多节点共享存储

在Kubernetes中为Elasticsearch配置多节点共享存储(ReadWriteMany)需结合存储后端特性及Elasticsearch架构设计。 由于Elasticsearch默认要求每个节点独立存储数据(ReadWriteOnce),直接实现多节点共享存储需特殊处理。 ​​方案一:使用支持ReadWriteMany的存储后端(推荐…

SpringBoot热部署与配置技巧

配置文件SpringBoot 的热部署Spring为开发者提供了一个名为spring-boot-devtools的模块来使SpringBoot应用支持热部署&#xff0c;提高开发者的开发效率&#xff0c;无需手动重启SpringBoot应用相关依赖&#xff1a;<dependency> <groupId>org.springframework.boo…

Python与C#的三元运算符的写法区别

一、语法结构对比​​PyTorch示例​​dev torch.device("cuda:0" if torch.cuda.is_available() else "cpu")​​逻辑​​&#xff1a;若torch.cuda.is_available()为真&#xff0c;则返回"cuda:0"&#xff0c;否则返回"cpu"。​​作…

java 学习篇一

java知识点 一、windows不区分大小写&#xff0c;linux区分大小写 二、写java需要JDK&#xff0c;一般运行环境需要JRE 三、JDK安装一般是傻瓜是安装 四、java主要工具javac、java&#xff1b;其中javac用于编译.java -> .class&#xff1b;java用于执行.class文件执行时候不…

仙盟数据库应用-外贸标签打印系统 前端数据库-V8--毕业论文-—-—仙盟创梦IDE

基于 Excel 标签打印软件的外贸打印流程优化与实践摘要&#xff1a;在全球化外贸业务中&#xff0c;标签打印是货物流通、信息标识的关键环节。本文聚焦 “未来之窗云上打印技术” 的 Excel 标签打印软件&#xff0c;结合外贸平台实际场景&#xff0c;分析其在打印流程中的应用…

【Linux】权限详解 权限本质、权限属性、su、sudo提权、chmod\chown\chgrp、文件类别

文章目录一、权限的认识二、linux的权限本质三、linux的用户su指令sudo提权四、linux角色五、文件权限属性六、修改权限的指令操作chmod指令(权限只会验证一次)chown/chgrp指令修改文件权限的八进制方案七、文件类别详解一、权限的认识 什么是权限&#xff1f; 生活中处处都有权…

rman清理归档

1进入rman rman target / 2&#xff1a;列出所有归档日志的路径 LIST ARCHIVELOG ALL; 3.然后在执行 crosscheck archivelog all;&#xff08;检查 RMAN 存储库中记录的归档日志是否在磁盘或备份存储中实际存在。 4.然后在执行 delete noprompt expired archivelog all;&…

Selenium 处理动态网页与等待机制详解

在使用 Selenium 进行网页自动化操作时&#xff0c;动态网页往往是开发者遇到的第一个 “拦路虎”。想象一下&#xff1a;你明明在代码中写好了元素定位逻辑&#xff0c;运行时却频繁报错 “元素不存在”&#xff0c;但手动打开网页时元素明明就在眼前 —— 这很可能是因为网页…

Salesforce 与外部系统实时集成:基于事件驱动的异步集成架构

在 Salesforce 与外部系统&#xff08;如 ERP、财务系统、物流系统等&#xff09;的实时集成中&#xff0c;“稳定性” 是核心挑战 —— 既要保证数据同步的及时性&#xff0c;又要应对网络波动、系统故障、并发冲突等不可控因素。以下从问题本质、技术瓶颈、解决方案细节三个维…

React 的 `cache()` 函数

文章目录前言一、核心作用二、工作原理三、使用场景1. 避免重复数据请求2. 优化昂贵计算四、缓存规则详解五、与其它缓存方式对比六、服务端特殊行为七、最佳实践八、缓存失效策略九、使用限制十、与数据获取库集成总结&#xff1a;何时使用 cache()前言 React 的 cache() 函数…

大白编译——autotools与cmake

注意: 本文内容于 2025-07-20 01:58:56 创建,可能不会在此平台上进行更新。如果您希望查看最新版本或更多相关内容,请访问原文地址:大白编译——autotools与cmake。感谢您的关注与支持! 之前记录了通过autotools编译rpm包与deb包的步骤。参考小白编译——rpm包与deb包 - …

react19+nextjs+antd切换主题颜色

在 React 19 Next.js Ant Design 项目中实现主题切换功能&#xff0c;可以通过以下步骤完成。这里将提供完整方案&#xff0c;包含静态主题切换和动态实时切换两种方式。一、基础配置&#xff08;Ant Design 主题支持&#xff09; 1. 安装必要依赖 npm install antd ant-desi…

Modbus Slave 使用教程:快速搭建模拟从站进行测试与开发

文章目录Modbus Slave 使用教程&#xff1a;快速搭建模拟从站进行测试与开发步骤详解&#xff1a;搭建 Modbus Slave1. 安装与启动2. 配置从站连接 (Connection Setup)连接3. 定义从站数据 (设置寄存器/线圈映射)4. 设置初始值与变化模式 (可选但重要)5. 连接 Master 进行测试高…

通俗易懂神经网络:从基础到实现

引言 神经网络是人工智能和深度学习的核心&#xff0c;它模仿人脑的工作方式&#xff0c;通过数据学习复杂的模式。本文将以通俗易懂的方式讲解神经网络的基础知识&#xff0c;包括单层神经网络、多层神经网络&#xff0c;最后用Python代码实现一个简单的神经网络模型。1. 神经…

【Linux】基本指令详解(三) 指令本质、三个查找指令、打包压缩、重要热键、linux体系结构、命令行解释器

文章目录date指令cal指令find指令(指令本质也是文件)which指令file指令whereis指令alias指令grep指令top指令打包和压缩指令zip/unzip指令关于rzsz(linux与windows互传 )tar指令linux机器之间互传bc指令uname指令(查看linux机器体系结构)几个重要的热键[Tab]按键[Ctrl]c按键[Ct…

MSTP 多生成树协议

MSTP 多生成树协议 STP/RSTP 的局限性 所有 vlan 共享一颗生成树无法实现不同 vlan 在多条 Trunk 链路上的分担 二层链路负载均衡STP/RSTP 的局限——次优二层路径**次优二层路径&#xff08;Suboptimal Layer 2 Path&#xff09; 是指&#xff1a; ** 数据帧在交换网络中传输时…