Go 语言即时通讯系统开发日志-day1:从简单消息收发 Demo 起步

Go语言即时通讯系统开发日志day1,主要模拟实现的一个简单的发送消息和接受消息的小demo,因为也才刚学习go语言的语法,对go的json、net/http库了解不多,所以了解了一下go语言的encoding/json库net/http库,以及websocket

总结:实现了极简的”聊天“demo,不能够支持不同用户的显示,无单聊,群聊,未使用MySQL保存数据,Redis作为缓存。希望明天可以完成数据库对数据存储,支持双人聊天,支持查看历史聊天记录。

学习方法反思不要好高骛远,只是完成了一个小demo,却在学习过程找了一些github上的高星IM来看,却实现不了,后续在完成聊天模块,联系人模块,群组模块等时可以在查看github的高星项目向其参考学习;不要追求完美,学习到一个知识点的时候,如json,http包,不要过多学习掌握即可,不用在浏览器中搜索过多页面进行查看,仅选择一俩个即可,最好可以写一篇简单的博客进行总结加深印象,使用ai也同样,使用一个或两个即可,不要过对比,浪费时间。

之前只是初略的了解了go语言支持json格式,但不了解作用是什么,以及json库的作用;所以我写了一个博客,Go语言:json 作用和语法,简单介绍了 json 的作用(指定字段名、忽略空值、忽略字段),encoding/json的两个常用函数Marshal序列化和Unmarshal反序列化。

定义消息类型

type Message struct {Sender    string `json:"sender"`Content   string `json:"content"`Timestamp int64  `json:"timestamp"`
}

构建服务器

func main() {// 初始化路由http.HandleFunc("/ws", handleConnections)// 添加静态文件服务,用于测试HTML客户端http.Handle("/", http.FileServer(http.Dir("./web")))// 启动服务器log.Println("Server started on :8080")err := http.ListenAndServe(":8080", nil)if err != nil {log.Fatal("ListenAndServe: ", err)}
}var upgrater = websocket.Upgrader{ReadBufferSize:  1024,WriteBufferSize: 1024,
}// 客户端连接
type Client struct {conn *websocket.Connsend chan []byte
}func handleConnections(w http.ResponseWriter, r *http.Request) {// 升级 HTTP 为 WebSocketconn, err := upgrater.Upgrade(w, r, nil)if err != nil {log.Println(err)return}defer conn.Close()// 创建客户端client := &Client{conn: conn,send: make(chan []byte),}// 启动读写goroutinego client.writePump()client.readPump()
}
  • 每个客户端连接由一个Client对象表示

  • 每个连接使用两个 goroutine 处理读写操作:

    • 读流程readPump持续读取消息 → 处理消息 → 可能通过client.send发送响应
    • 写流程:其他 goroutine 向client.send发送数据 → writePump将数据发送到 WebSocket
  • 使用通道client.send在两个 goroutine 之间传递消息

发送消息

func (c *Client) writePump() {defer c.conn.Close()for {select {case message, ok := <-c.send:if !ok {// 通道关闭c.conn.WriteMessage(websocket.CloseMessage, []byte{})return}if err := c.conn.WriteMessage(websocket.TextMessage, message); err != nil {log.Println("write error:", err)return}}}
}

WebSocket 客户端的 “写泵”(write pump) 函数,将消息从客户端的发送通道 (c.send) 持续写入 WebSocket 连接。

  • 持续监听c.send通道,一旦有消息就发送到 WebSocket 服务器
  • 当通道关闭时,主动向服务器发送关闭消息并结束函数
  • 处理发送过程中可能出现的错误

读取消息

func (c *Client) readPump() {defer c.conn.Close()for {_, message, err := c.conn.ReadMessage()if err != nil {log.Println("read error:", err)break}// 处理接收到的消息log.Printf("Received: %s", message)}
}

WebSocket 客户端的 “读泵”(read pump) 功能,负责持续从服务器接收消息。

  • 持续监听 WebSocket 连接,读取服务器发送的消息
  • 处理读取过程中出现的错误
  • 将接收到的消息进行日志记录或进一步处理

运行

  1. 确保项目结构如下:

    im-go/
    ├── main.go
    └── public/├── index.html└── client.js
    
  2. 安装依赖:go get github.com/gorilla/websocket

  3. 启动服务器:go run main.go

  4. 打开浏览器访问:http://localhost:8080

 2025-05-12 173310.png

后端代码

main.go

package mainimport ("log""net/http""github.com/gorilla/websocket"
)type Message struct {Sender    string `json:"sender"`Content   string `json:"content"`Timestamp int64  `json:"timestamp"`
}func main() {// 初始化路由http.HandleFunc("/ws", handleConnections)// 添加静态文件服务,用于测试HTML客户端http.Handle("/", http.FileServer(http.Dir("./web")))// 启动服务器log.Println("Server started on :8080")err := http.ListenAndServe(":8080", nil)if err != nil {log.Fatal("ListenAndServe: ", err)}
}var upgrater = websocket.Upgrader{ReadBufferSize:  1024,WriteBufferSize: 1024,
}// 客户端连接
type Client struct {conn *websocket.Connsend chan []byte
}func handleConnections(w http.ResponseWriter, r *http.Request) {// 升级 HTTP 为 WebSocketconn, err := upgrater.Upgrade(w, r, nil)if err != nil {log.Println(err)return}defer conn.Close()// 创建客户端client := &Client{conn: conn,send: make(chan []byte),}// 启动读写goroutinego client.writePump()client.readPump()
}func (c *Client) readPump() {defer c.conn.Close()for {_, message, err := c.conn.ReadMessage()if err != nil {log.Println("read error:", err)break}// 处理接收到的消息log.Printf("Received: %s", message)}
}func (c *Client) writePump() {defer c.conn.Close()for {select {case message, ok := <-c.send:if !ok {// 通道关闭c.conn.WriteMessage(websocket.CloseMessage, []byte{})return}if err := c.conn.WriteMessage(websocket.TextMessage, message); err != nil {log.Println("write error:", err)return}}}
}

前端代码

前端代码虽然是ai生成的,我还是看了 3小时前端入门教程(HTML+CSS+JS),了解了一下这三者是什么,以及作用

HTML(超文本标记语言)

  • 是什么
    HTML 是网页的​​结构和内容层​​,通过标签(如 <h1><p><div>)定义页面的文本、图片、链接等元素。
  • 作用:
    • 搭建网页的骨架(例如标题、段落、表单)。
    • 提供语义化结构(如 <header><article>),便于搜索引擎和屏幕阅读器理解。

CSS(层叠样式表)

  • 是什么
    CSS 是网页的​​表现层​​,控制 HTML 元素的外观(颜色、布局、字体等)。
  • 作用:
    • 美化页面(如响应式设计、动画效果)。
    • 实现布局(Flexbox、Grid 等)。

JavaScript(JS)

  • 是什么
    JavaScript 是网页的​​行为层​​,一种编程语言,用于实现交互和动态功能。
  • 作用:
    • 处理用户操作(点击、输入等)。
    • 动态更新内容(如加载数据、DOM 操作)。
    • 与后端交互(通过 AJAX 或 Fetch API)。

后续的话前端可能就用ai生成vue的了

Vue 是什么?

一个用于构建用户界面的 JavaScript 框架,核心特点是:

  1. 响应式数据:数据变,视图自动更新。
  2. 组件化:把页面拆成可复用的组件。
  3. 易上手:类似 HTML 的模板语法,学习成本低。

Vue 的作用

  • 替代 jQuery,动态交互更简单(如实时搜索、表单验证)。
  • 开发单页应用(SPA)(如后台管理系统)。
  • 搭配插件(Vue Router、Pinia)做复杂项目。

index.html

<!DOCTYPE html>
<html><head><title>Go Chat Demo</title><script src="client.js"></script>
</head><body><h1>Go Chat Demo</h1><div id="messages" style="height:300px;overflow:auto;border:1px solid #ccc;"></div><input type="text" id="messageInput" placeholder="Type a message..."><button onclick="sendMessage()">Send</button>
</body></html>

client.js

var ws;function connect() {ws = new WebSocket("ws://" + window.location.host + "/ws");ws.onopen = function () {console.log("Connected to server");addMessage("System: Connected to server");};ws.onmessage = function (event) {console.log("Message received:", event.data);addMessage("Server: " + event.data);};ws.onclose = function () {console.log("Disconnected from server");addMessage("System: Disconnected from server");// 尝试5秒后重连setTimeout(connect, 5000);};ws.onerror = function (err) {console.log("WebSocket error:", err);};
}function addMessage(msg) {var messages = document.getElementById("messages");messages.innerHTML += "<p>" + msg + "</p>";messages.scrollTop = messages.scrollHeight;
}function sendMessage() {var input = document.getElementById("messageInput");var message = input.value;if (message && ws.readyState === WebSocket.OPEN) {ws.send(message);addMessage("You: " + message);input.value = "";}
}// 页面加载时连接
window.onload = connect;

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

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

相关文章

基于vllm-ascend的华为atlas大模型部署

vllm-ascend介绍&#xff1a; vLLM 昇腾插件 (vllm-ascend) 是一个让vLLM在Ascend NPU无缝运行的后端插件。 此插件是 vLLM 社区中支持昇腾后端的推荐方式。它遵循[RFC]: Hardware pluggable所述原则&#xff1a;通过解耦的方式提供了vLLM对Ascend NPU的支持。 使用 vLLM 昇腾…

贝叶斯优化Transformer融合支持向量机多变量时间序列预测,Matlab实现

贝叶斯优化Transformer融合支持向量机多变量时间序列预测&#xff0c;Matlab实现 目录 贝叶斯优化Transformer融合支持向量机多变量时间序列预测&#xff0c;Matlab实现效果一览基本介绍程序设计参考资料 效果一览 基本介绍 1.BO-TransformerSVM多变量时间序列预测&#xff0c…

状压DP总结

前言 一般来讲 n n n 数据范围在 10 ~ 25 之间都是可以进行状态压缩的 -> 2 n 2^n 2n 状压 The 2024 Shanghai Collegiate Programming Contest Problem G.象棋大师 知识点&#xff1a;线性DP&#xff0c;状压DP&#xff0c;预处理 辅助转移的技巧 首先看到 n*n 的方格…

SQLite 转换为 MySQL 数据库

一、导出 SQLite 数据库 1. 使用 SQLite 命令行工具 • 打开终端&#xff08;在 Linux 或 macOS 上&#xff09;或命令提示符&#xff08;在 Windows 上&#xff09;。 • 输入sqlite3 your_database_name.db&#xff08;将 your_database_name.db 替换为你的 SQLite 数据库…

【技巧】使用UV创建python项目的开发环境

回到目录 【技巧】使用UV创建python项目的开发环境 0. 为什么用UV 下载速度快、虚拟环境、多版本python支持、清晰的依赖关系 1. 安装基础软件 1.1. 安装python 下载地址&#xff1a;https://www.python.org/downloads/windows/ 1.2. 安装UV > pip install uv -i ht…

Java SpringMVC 和 MyBatis 整合项目的事务管理配置详解

目录 一、事务管理的基本概念二、在 SpringMVC 和 MyBatis 整合项目中配置事务管理1. 配置数据源2. 配置事务管理器3. 使用事务注解4. 配置 MyBatis 的事务支持5. 测试事务管理三、总结在企业级应用开发中,事务管理是确保数据一致性和完整性的重要机制。特别是在整合了 Spring…

Nakama:让游戏与应用更具互动性和即时性

在现代游戏和应用程序开发中,实现社交互动和实时功能已成为用户体验的核心需求。为满足这种需求,许多开发者正转向分布式服务器技术,在这些技术中,Nakama 构建起了一座桥梁。Nakama 是一个开源的分布式服务器,专门为社交和实时游戏及应用程序设计,为开发者提供了强大的工…

项目中会出现的css样式

1.重复渐变边框 思路&#xff1a; 主要是用重复的背景渐变实现的 如图&#xff1a; <div class"card"><div class"container">全面收集中医癌毒临床医案&#xff0c;建立医案共享机制&#xff0c;构建癌毒病机知识图谱&#xff0c;便于医疗人…

数组和切片的区别

&#x1f49d;&#x1f49d;&#x1f49d;欢迎来到我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里可以感受到一份轻松愉快的氛围&#xff0c;不仅可以获得有趣的内容和知识&#xff0c;也可以畅所欲言、分享您的想法和见解。 非常期待和您一起在这个小…

Jenkins企业级实战

目标 在Windows操作系统上使用Jenkins完成代码的自动拉取、编译、打包、发布工作。 实施 1.安装Java开发工具包&#xff08;JDK&#xff09; Jenkins是基于Java的应用程序&#xff0c;因此需要先安装JDK。可以从Oracle官网或OpenJDK下载适合的JDK版本。推荐java17版本&#x…

C++ 异常捕获 try 和 __try的区别笔记

最近碰到了try 和 __try的区别的问题&#xff0c;经过实测与验证&#xff0c;发现在vs2019下&#xff0c;确实存在try无法捕获特定异常的问题&#xff0c;比如下面的代码&#xff1a; //以空格作为分割符的符号个数 //内存复制功能 // test1.cpp : 定义控制台应用程序的入口点…

Spark基础介绍

1. Spark 核心概念 1.1 RDD&#xff08;弹性分布式数据集&#xff09; 定义&#xff1a;RDD&#xff08;Resilient Distributed Dataset&#xff09;是 Spark 的核心抽象&#xff0c;是不可变、可分区、容错的分布式数据集合。特性&#xff1a; 弹性&#xff1a;自动进行内存…

采用SqlSugarClient创建数据库实例引发的异步调用问题

基于SqlSugar编写的多个WebApi接口&#xff0c;项目初始化时采用单例模式注册SqlSugarClient实例对象&#xff0c;前端页面采用layui布局&#xff0c;并在一个按钮事件中通过Ajax连续调用多个WebApi接口获取数据。实际运行时点击按钮会随机报下面几种错误&#xff1a; Execute…

[原创](现代Delphi 12指南):[macOS 64bit App开发]: 如何获取当前用户主目录(即:~波浪符号目录)?

[作者] 常用网名: 猪头三 出生日期: 1981.XX.XX 企鹅交流: 643439947 个人网站: 80x86汇编小站 编程生涯: 2001年~至今[共24年] 职业生涯: 22年 开发语言: C/C++、80x86ASM、Object Pascal、Objective-C、C#、R、Python、PHP、Perl、 开发工具: Visual Studio、Delphi、XCode、…

pdf url 转 图片

背景&#xff1a;vue2.0需要把pdf转成图片&#xff0c;显示在url里面&#xff0c;使用pdfjs-dist来解决 步骤&#xff1a; 1、安装依赖包(我的项目是node12&#xff0c;安装太高版本会报错) npm i pdfjs-dist2.16.105 2、vue代码 <template><div class"main…

理解 Open vSwitch (OVS)

Open vSwitch&#xff08;简称 OVS&#xff09;是一个开源的 虚拟交换机&#xff0c;主要用于 虚拟化环境&#xff08;如 KVM、Xen、Docker&#xff09;和 软件定义网络&#xff08;SDN&#xff09;。它类似于物理交换机&#xff0c;但在软件层面实现&#xff0c;可以灵活地管理…

S7-1500——零基础入门1、工业编程基本概念

工业编程基本概念 一,数制与基本数据类型二,数字量信号三,模拟量信号一,数制与基本数据类型 本节主要内容 类别内容主题数制与基本数据类型数制讲解十进制、十六进制、二进制及其进位规则;基数、位权概念数据类型介绍PLC 使用的数据类型:未序列数据类型(bit、byte、wor…

kotlin-协程(什么是一个协程)

1.什么指一个协程对于线程来说一个thread就是就是指一个线程&#xff0c;thread为什么成为线程呢&#xff1f;因为他实现了对线程的一个抽象管理&#xff0c;可以管理这个线程&#xff0c;启动&#xff0c;可以查看各种信息 那么协程呢&#xff1f; public fun CoroutineScop…

七、深入 Hive DDL:管理表、分区与洞察元数据

作者&#xff1a;IvanCodes 日期&#xff1a;2025年5月13日 专栏&#xff1a;Hive教程 内容导航 一、表的 DDL 操作 (非创建)二、分区的 DDL 操作三、洞察元数据&#xff1a;SHOW 命令的威力结语&#xff1a;DDL 与 SHOW&#xff0c;Hive 管理的双翼练习题一、选择题二、代码题…

【 Redis | 实战篇 短信登录 】

前言&#xff1a; 主要完成了基于Session实现登录&#xff0c;解决集群的Session共享问题&#xff0c;从而实现了基于Redis来实现共享Session登录 1.基于Session实现登录 1.1.发送短信验证码 步骤&#xff1a; 前端提交手机号 》校验手机号 》不符合返回错误信息&#xff0…