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.pswp.cn/web/79770.shtml
繁體地址,請注明出處:http://hk.pswp.cn/web/79770.shtml
英文地址,請注明出處:http://en.pswp.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…