Using Go to Create a Real-time Chat Server

Table of Contents

  1. Introduction
  2. Prerequisites
  3. Setup
  4. Creating the Chat Server
  5. Building the Frontend
  6. Running the Chat Server
  7. Conclusion


Introduction

In this tutorial, we will explore how to use Go (Golang) to create a real-time chat server. By the end of this tutorial, you will have a functioning chat server that allows multiple users to communicate with each other in real-time.

We will cover the necessary setup, building the chat server, and creating a simple frontend interface using HTML and JavaScript. This tutorial assumes you have basic knowledge of Go programming and web development concepts.

Prerequisites

To follow along with this tutorial, you will need:

  • Basic knowledge of the Go programming language
  • A text editor or integrated development environment (IDE) to write Go code
  • A web browser to test and interact with the chat application

Setup

Before we begin, ensure that you have Go installed on your system. You can download and install Go by following the official documentation: https://golang.org/doc/install

Once Go is installed, open a terminal or command prompt and verify the installation by running the following command:

go version

You should see the installed Go version displayed.

Creating the Chat Server

Now, let’s start building the chat server. Create a new directory for your project, and inside that directory, create a new Go file named server.go. Open server.go in your chosen text editor or IDE.

First, let’s import the necessary packages:

package main

import (
    "fmt"
    "log"
    "net/http"
)

Next, we’ll define a function to handle incoming WebSocket connections:

func handleConnections(w http.ResponseWriter, r *http.Request) {
    // WebSocket logic goes here
}

Inside the handleConnections function, we need to upgrade the HTTP connection to a WebSocket connection, allowing for bidirectional communication. To do this, add the following code:

func handleConnections(w http.ResponseWriter, r *http.Request) {
    // Upgrade initial GET request to a WebSocket
    ws, err := upgrader.Upgrade(w, r, nil)
    if err != nil {
        log.Fatal(err)
    }
    // Register new client
    client := &Client{socket: ws}
    clients[client] = true

    // Listen for messages from the client
    go client.read()

    // Send received messages to all clients
    go client.broadcast()
}

We also need to define a main function to start the chat server:

func main() {
    // Configure the WebSocket route
    http.HandleFunc("/ws", handleConnections)

    // Start the server on localhost:8000
    log.Println("Chat server started on localhost:8000")
    err := http.ListenAndServe(":8000", nil)
    if err != nil {
        log.Fatal(err)
    }
}

Now, let’s define the Client struct and its associated methods. The Client struct represents a connected client:

type Client struct {
    socket *websocket.Conn
}

func (c *Client) read() {
    // Read logic goes here
}

func (c *Client) broadcast() {
    // Broadcast logic goes here
}

Inside the read method, we’ll continuously listen for messages from the client and handle them accordingly:

func (c *Client) read() {
    defer func() {
        // Close the connection when read goroutine exits
        c.socket.Close()
        delete(clients, c)
    }()

    for {
        _, message, err := c.socket.ReadMessage()
        if err != nil {
            log.Printf("Error occurred: %v", err)
            break
        }
        // Handle received message here
    }
}

In the broadcast method, we’ll send messages received from one client to all connected clients:

func (c *Client) broadcast() {
    defer func() {
        // Close the channel when broadcast goroutine exits
        c.socket.Close()
        delete(clients, c)
    }()

    for {
        message := <-c.send
        for client := range clients {
            err := client.socket.WriteJSON(message)
            if err != nil {
                log.Printf("Error occurred: %v", err)
                client.socket.Close()
                delete(clients, client)
            }
        }
    }
}

That’s it! You have now created the backend logic for the chat server using Go.

Building the Frontend

In this section, we’ll create a simple HTML and JavaScript frontend to interact with the chat server.

Create a new HTML file named index.html and copy the following code into it:

<!DOCTYPE html>
<html>
<head>
    <title>Real-time Chat Server</title>
    <style>
        /* Add CSS styles here */
    </style>
</head>
<body>
    <div id="chat"></div>
    <input type="text" id="input" />
    <script>
        // Add JavaScript code here
    </script>
</body>
</html>

Inside the <style> tag, you can add CSS styles to enhance the appearance of the chat interface.

In the <script> tag, we’ll use JavaScript to handle the WebSocket connections and enable real-time chat functionality. Copy the following code into the <script> tag:

const socket = new WebSocket("ws://localhost:8000/ws");

socket.onopen = function() {
    console.log("Connected to server");
};

socket.onmessage = function(e) {
    // Handle received messages here
};

socket.onclose = function() {
    console.log("Connection closed");
};

document.getElementById("input").addEventListener("keyup", function(event) {
    if (event.keyCode === 13) {
        const message = this.value;
        socket.send(message);
        this.value = "";
    }
});

This JavaScript code establishes a WebSocket connection to the chat server, handles incoming messages, and sends messages when the user presses the Enter key in the input field.

Running the Chat Server

To run the chat server, open a terminal or command prompt, navigate to the directory containing the server.go file, and execute the following command:

go run server.go

You should see the message Chat server started on localhost:8000 indicating that the server is running.

Now, open a web browser and navigate to http://localhost:8000/index.html to access the chat interface. Open multiple browser tabs to simulate multiple users and start chatting in real-time!

Conclusion

In this tutorial, you learned how to use Go to create a real-time chat server. We covered setting up Go, building the chat server logic, creating a simple frontend, and running the chat server.

You can further enhance the chat server by adding features like user authentication, private messaging, and message history. Experiment with the code and explore more possibilities to make the chat server more robust and user-friendly.

Happy chatting!