亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

使用Go語言實現簡單聊天系統(tǒng)

 更新時間:2024年10月05日 09:55:43   作者:小于負無窮  
本文介紹了如何使用Go語言和WebSocket技術構建一個簡單的多人聊天室系統(tǒng),包括客戶端連接管理、消息廣播和并發(fā)處理,最后,通過編寫main.go、hub.go和client.go等核心代碼模塊,具有一定的參考價值,感興趣的可以了解一下

在互聯網時代,聊天系統(tǒng)是常見的應用場景之一。無論是即時通訊、在線客服還是多人游戲中的消息系統(tǒng),聊天功能的實現都是必不可少的。本文將使用 Go 語言,結合 WebSocket 來構建一個簡單的多人聊天室系統(tǒng)。

一、項目結構

首先,我們設計一個簡單的項目結構,文件結構如下:

go-chat/
│
├── main.go          // 主程序
├── client.go        // 處理客戶端連接
└── hub.go           // 消息管理

WebSocket 簡介

WebSocket 是一種基于 TCP 的網絡協議,允許客戶端和服務端建立持久的全雙工通信連接。相比于傳統(tǒng)的 HTTP 請求-響應模型,WebSocket 更加適合實時通信場景,因此它是實現聊天系統(tǒng)的理想選擇。

二、實現思路

  • 客戶端連接管理:每個客戶端通過 WebSocket 連接到服務器,服務器會為每個連接的客戶端分配一個唯一的 connection。
  • 消息廣播:當某個客戶端發(fā)送消息時,服務器將該消息廣播給所有連接的客戶端。
  • 并發(fā)處理:Go 原生支持并發(fā)編程,通過 Goroutine 和 Channel 可以輕松處理并發(fā)消息傳遞。

三、詳細實現

1. main.go - 啟動 WebSocket 服務

package main

import (
    "log"
    "net/http"
)

func main() {
    hub := newHub()
    go hub.run()

    http.HandleFunc("/ws", func(w http.ResponseWriter, r *http.Request) {
        serveWs(hub, w, r)
    })

    log.Println("服務器啟動,監(jiān)聽端口 8080...")
    err := http.ListenAndServe(":8080", nil)
    if err != nil {
        log.Fatal("監(jiān)聽失敗:", err)
    }
}

main.go 文件的作用是啟動 HTTP 服務器,并在 /ws 路徑上處理 WebSocket 連接請求。

2. hub.go - 消息管理中心

Hub 負責管理所有的客戶端連接,以及消息的廣播。

package main

// Hub 負責管理所有客戶端的注冊、注銷及消息廣播
type Hub struct {
    clients    map[*Client]bool // 已連接的客戶端
    broadcast  chan []byte      // 從客戶端接收的廣播消息
    register   chan *Client     // 注冊請求
    unregister chan *Client     // 注銷請求
}

func newHub() *Hub {
    return &Hub{
        clients:    make(map[*Client]bool),
        broadcast:  make(chan []byte),
        register:   make(chan *Client),
        unregister: make(chan *Client),
    }
}

func (h *Hub) run() {
    for {
        select {
        case client := <-h.register:
            h.clients[client] = true
        case client := <-h.unregister:
            if _, ok := h.clients[client]; ok {
                delete(h.clients, client)
                close(client.send)
            }
        case message := <-h.broadcast:
            for client := range h.clients {
                select {
                case client.send <- message:
                default:
                    close(client.send)
                    delete(h.clients, client)
                }
            }
        }
    }
}
  • clients:保存當前連接的所有客戶端。
  • broadcast:一個通道,用于廣播消息給所有客戶端。
  • register/unregister:用于客戶端連接和斷開的注冊和注銷。

3. client.go - 處理客戶端連接

每個客戶端的連接由 Client 結構體表示,并包含了 WebSocket 連接和發(fā)送消息的通道。

package main

import (
    "github.com/gorilla/websocket"
    "log"
    "net/http"
    "time"
)

const (
    writeWait = 10 * time.Second
    pongWait  = 60 * time.Second
    pingPeriod = (pongWait * 9) / 10
)

var upgrader = websocket.Upgrader{
    ReadBufferSize:  1024,
    WriteBufferSize: 1024,
}

type Client struct {
    hub  *Hub
    conn *websocket.Conn
    send chan []byte
}

func serveWs(hub *Hub, w http.ResponseWriter, r *http.Request) {
    conn, err := upgrader.Upgrade(w, r, nil)
    if err != nil {
        log.Println("升級到 WebSocket 失敗:", err)
        return
    }
    client := &Client{hub: hub, conn: conn, send: make(chan []byte, 256)}
    client.hub.register <- client

    go client.writePump()
    go client.readPump()
}

func (c *Client) readPump() {
    defer func() {
        c.hub.unregister <- c
        c.conn.Close()
    }()
    c.conn.SetReadLimit(512)
    c.conn.SetReadDeadline(time.Now().Add(pongWait))
    c.conn.SetPongHandler(func(string) error { c.conn.SetReadDeadline(time.Now().Add(pongWait)); return nil })

    for {
        _, message, err := c.conn.ReadMessage()
        if err != nil {
            if websocket.IsUnexpectedCloseError(err, websocket.CloseGoingAway, websocket.CloseAbnormalClosure) {
                log.Printf("讀取錯誤: %v", err)
            }
            break
        }
        c.hub.broadcast <- message
    }
}

func (c *Client) writePump() {
    ticker := time.NewTicker(pingPeriod)
    defer func() {
        ticker.Stop()
        c.conn.Close()
    }()

    for {
        select {
        case message, ok := <-c.send:
            c.conn.SetWriteDeadline(time.Now().Add(writeWait))
            if !ok {
                c.conn.WriteMessage(websocket.CloseMessage, []byte{})
                return
            }

            w, err := c.conn.NextWriter(websocket.TextMessage)
            if err != nil {
                return
            }
            w.Write(message)

            n := len(c.send)
            for i := 0; i < n; i++ {
                w.Write(<-c.send)
            }

            if err := w.Close(); err != nil {
                return
            }

        case <-ticker.C:
            c.conn.SetWriteDeadline(time.Now().Add(writeWait))
            if err := c.conn.WriteMessage(websocket.PingMessage, nil); err != nil {
                return
            }
        }
    }
}
  • serveWs:處理每個 WebSocket 連接請求,并為每個連接創(chuàng)建一個客戶端實例。
  • readPump:從 WebSocket 連接中讀取消息,并將消息廣播到所有客戶端。
  • writePump:負責將消息發(fā)送給客戶端,并定期發(fā)送心跳檢測(ping)消息以保持連接。

四、運行項目

首先,安裝 WebSocket 依賴:

go get github.com/gorilla/websocket

編寫前端 HTML 頁面(可用于測試),例如 index.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Go 聊天室</title>
</head>
<body>
    <div id="chatbox"></div>
    <input id="msg" type="text" />
    <button onclick="sendMessage()">發(fā)送</button>

    <script>
        var ws = new WebSocket("ws://localhost:8080/ws");
        ws.onmessage = function(event) {
            var chatbox = document.getElementById('chatbox');
            chatbox.innerHTML += event.data + "<br/>";
        };

        function sendMessage() {
            var msg = document.getElementById("msg").value;
            ws.send(msg);
        }
    </script>
</body>
</html>

運行 Go 服務:

go run main.go

打開瀏覽器,訪問 index.html,即可體驗多人聊天室的功能。

到此這篇關于使用Go語言實現簡單聊天系統(tǒng)的文章就介紹到這了,更多相關Go語言聊天系統(tǒng)內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!

相關文章

  • go語言區(qū)塊鏈實戰(zhàn)實現簡單的區(qū)塊與區(qū)塊鏈

    go語言區(qū)塊鏈實戰(zhàn)實現簡單的區(qū)塊與區(qū)塊鏈

    這篇文章主要為大家介紹了go語言區(qū)塊鏈的實戰(zhàn)學習,來實現簡單的區(qū)塊與區(qū)塊鏈示例過程,有需要的朋友可以借鑒參考下,希望能夠有所幫助
    2021-10-10
  • Golang必知必會之Go?Mod命令詳解

    Golang必知必會之Go?Mod命令詳解

    go mod可以使項目從GOPATH的強制依賴中獨立出來,也就是說你的項目依賴不再需要放在在GOPATH下面了,下面這篇文章主要給大家介紹了關于Golang必知必會之Go?Mod命令的相關資料,文中通過實例代碼介紹的非常詳細,需要的朋友可以參考下
    2022-07-07
  • golang?gin框架實現大文件的流式上傳功能

    golang?gin框架實現大文件的流式上傳功能

    這篇文章主要介紹了golang?gin框架中實現大文件的流式上傳,本文通過實例代碼給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2022-07-07
  • go語言實現接口查詢

    go語言實現接口查詢

    這篇文章主要介紹了go語言實現接口查詢,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2020-12-12
  • Go簡單實現協程池的實現示例

    Go簡單實現協程池的實現示例

    本文主要介紹了Go簡單實現協程池的實現示例,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2022-06-06
  • Go語言高效編程的3個技巧總結

    Go語言高效編程的3個技巧總結

    Go語言是一種開源編程語言,可輕松構建簡單、可靠且高效的軟件,下面這篇文章主要給大家分享介紹了關于Go語言高效編程的3個技巧,文中通過實例代碼介紹的非常詳細,需要的朋友可以參考下
    2023-01-01
  • golang與pgsql交互的實現

    golang與pgsql交互的實現

    本文主要介紹了golang與pgsql交互的實現,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2023-03-03
  • Go語言中XML文件的讀寫操作

    Go語言中XML文件的讀寫操作

    本文主要介紹了Go語言中XML文件的讀寫操作,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2023-04-04
  • golang判斷兩個事件是否存在沖突的方法示例

    golang判斷兩個事件是否存在沖突的方法示例

    這篇文章主要為大家詳細介紹了golang判斷兩個事件是否存在沖突的方法示例,文中的示例代碼講解詳細,感興趣的小伙伴可以跟隨小編一起學習一下
    2023-10-10
  • golang 跳出for循環(huán)操作

    golang 跳出for循環(huán)操作

    這篇文章主要介紹了golang 跳出for循環(huán)操作,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2020-12-12

最新評論