SoFunction
Updated on 2025-03-02

Implementing a simple chat system using Go language

In the Internet era, chat systems are one of the common application scenarios. Whether it is instant messaging, online customer service or messaging systems in multiplayer games, the implementation of chat function is essential. This article will use Go language and combine WebSocket to build a simple multiplayer chat room system.

1. Project structure

First, we design a simple project structure with the file structure as follows:

go-chat/
│
├──           // Main program├──         // Handle client connections└──            // Message management

Introduction to WebSocket

WebSocket is a TCP-based network protocol that allows clients and servers to establish persistent full-duplex communication connections. Compared with the traditional HTTP request-response model, WebSocket is more suitable for real-time communication scenarios, so it is ideal for implementing a chat system.

2. Implementation ideas

  • Client connection management: Each client connects to the server through WebSocket, and the server will assign a unique client to each connected client.connection
  • Message broadcast: When a client sends a message, the server broadcasts the message to all connected clients.
  • Concurrent processing: Go natively supports concurrent programming, and concurrent messaging can be easily handled through Goroutine and Channel.

3. Detailed implementation

1.  - Start the WebSocket service

package main

import (
    "log"
    "net/http"
)

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

    ("/ws", func(w , r *) {
        serveWs(hub, w, r)
    })

    ("The server starts, listen to port 8080...")
    err := (":8080", nil)
    if err != nil {
        ("Supervisor failed:", err)
    }
}

The function of the file is to start the HTTP server and/wsProcess WebSocket connection requests on the path.

2.  -Message Management Center

HubResponsible for managing all client connections and broadcasting of messages.

package main

// Hub is responsible for managing registration, cancellation and message broadcast of all clientstype Hub struct {
    clients    map[*Client]bool // Connected client    broadcast  chan []byte      // Broadcast message received from the client    register   chan *Client     // Registration request    unregister chan *Client     // Logout request}

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 := <-:
            [client] = true
        case client := <-:
            if _, ok := [client]; ok {
                delete(, client)
                close()
            }
        case message := <-:
            for client := range  {
                select {
                case  <- message:
                default:
                    close()
                    delete(, client)
                }
            }
        }
    }
}
  • clients: Save all clients currently connected.
  • broadcast: A channel for broadcasting messages to all clients.
  • register/unregister: Registration and logout for client connections and disconnections.

3.  - Handle client connections

The connection to each client isClientStructure represents and contains the channel for WebSocket to connect and send messages.

package main

import (
    "/gorilla/websocket"
    "log"
    "net/http"
    "time"
)

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

var upgrader = {
    ReadBufferSize:  1024,
    WriteBufferSize: 1024,
}

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

func serveWs(hub *Hub, w , r *) {
    conn, err := (w, r, nil)
    if err != nil {
        ("Upgrade to WebSocket failed:", err)
        return
    }
    client := &Client{hub: hub, conn: conn, send: make(chan []byte, 256)}
     <- client

    go ()
    go ()
}

func (c *Client) readPump() {
    defer func() {
         <- c
        ()
    }()
    (512)
    (().Add(pongWait))
    (func(string) error { (().Add(pongWait)); return nil })

    for {
        _, message, err := ()
        if err != nil {
            if (err, , ) {
                ("Read Error: %v", err)
            }
            break
        }
         <- message
    }
}

func (c *Client) writePump() {
    ticker := (pingPeriod)
    defer func() {
        ()
        ()
    }()

    for {
        select {
        case message, ok := <-:
            (().Add(writeWait))
            if !ok {
                (, []byte{})
                return
            }

            w, err := ()
            if err != nil {
                return
            }
            (message)

            n := len()
            for i := 0; i < n; i++ {
                (<-)
            }

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

        case <-:
            (().Add(writeWait))
            if err := (, nil); err != nil {
                return
            }
        }
    }
}
  • serveWs: Process each WebSocket connection request and create a client instance for each connection.
  • readPump: Read messages from the WebSocket connection and broadcast messages to all clients.
  • writePump: Responsible for sending messages to the client and sending heartbeat detection (ping) messages regularly to keep the connection.

4. Run the project

First, install the WebSocket dependencies:

go get /gorilla/websocket

Write front-end HTML pages (can be used for testing), e.g.

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Go Chat Room</title>
</head>
<body>
    <div ></div>
    <input  type="text" />
    <button onclick="sendMessage()">send</button>

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

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

Run the Go service:

go run 

Open the browser and visit, you can experience the functions of multi-person chat rooms.

This is the end of this article about using Go to implement a simple chat system. For more related content on Go language chat system, please search for my previous articles or continue browsing the related articles below. I hope everyone will support me in the future!