Building a Real-Time Chat Application with Go and WebSockets

Table of Contents

  1. Introduction
  2. Prerequisites
  3. Setting up the Environment
  4. Creating a Basic Web Server
  5. Implementing WebSockets
  6. Creating the Chat Application
  7. Testing the Application
  8. Conclusion


Introduction

In this tutorial, we will build a real-time chat application using Go and WebSockets. You will learn how to set up a basic web server, implement WebSockets for real-time communication, and create a chat application that allows multiple users to chat simultaneously.

By the end of this tutorial, you will have a working chat application that can be expanded upon for further customization or integration into other projects.

Prerequisites

To follow along with this tutorial, you should have a basic understanding of the Go programming language and web development concepts. Familiarity with HTML, CSS, and JavaScript will be helpful but not mandatory.

Make sure you have Go installed on your machine. You can download and install Go from the official website: https://golang.org/dl/

Setting up the Environment

Before we start building our chat application, let’s set up the project environment.

  1. Create a new directory for your project: mkdir chat-app
  2. Navigate into the project directory: cd chat-app

  3. Initialize a new Go module: go mod init github.com/your-username/chat-app

Creating a Basic Web Server

We will begin by creating a basic web server using the net/http package in Go. This server will serve the static HTML, CSS, and JavaScript files required for our chat application.

  1. Create a new file called main.go.

  2. Open main.go in your preferred text editor.

    Add the following code to main.go:

     package main
        
     import (
     	"fmt"
     	"net/http"
     )
        
     func main() {
     	http.HandleFunc("/", handleHome)
     	http.ListenAndServe(":8080", nil)
     }
        
     func handleHome(w http.ResponseWriter, r *http.Request) {
     	http.ServeFile(w, r, "index.html")
     }
    

    Here, we define the handleHome function that serves the index.html file when the root URL is accessed.

  3. Save the changes and exit the text editor.

Implementing WebSockets

Now, let’s implement WebSockets in our chat application to enable real-time communication between the server and clients.

  1. Create a new file called chat.go.

  2. Open chat.go in your text editor.

    Add the following code to chat.go:

     package main
        
     import (
     	"log"
     	"net/http"
        
     	"github.com/gorilla/websocket"
     )
        
     var upgrader = websocket.Upgrader{
     	ReadBufferSize:  1024,
     	WriteBufferSize: 1024,
     }
        
     func handleWebSocket(w http.ResponseWriter, r *http.Request) {
     	conn, err := upgrader.Upgrade(w, r, nil)
     	if err != nil {
     		log.Println(err)
     		return
     	}
     	// TODO: Handle WebSocket logic here
     }
        
    

    Here, we import the gorilla/websocket package, which provides a WebSocket implementation for Go. We also define the handleWebSocket function that upgrades the HTTP connection to a WebSocket connection.

  3. Save the changes and exit the text editor.

Creating the Chat Application

Now that we have set up the basic web server and WebSocket functionality, let’s create the actual chat application.

  1. Open main.go in your text editor.

    Modify the handleHome function in main.go as follows:

     func handleHome(w http.ResponseWriter, r *http.Request) {
     	http.ServeFile(w, r, "index.html")
     }
        
     func handleWebSocket(w http.ResponseWriter, r *http.Request) {
     	conn, err := upgrader.Upgrade(w, r, nil)
     	if err != nil {
     		log.Println(err)
     		return
     	}
     	// TODO: Handle WebSocket logic here
     }
        
     func main() {
     	http.HandleFunc("/", handleHome)
     	http.HandleFunc("/ws", handleWebSocket)
     	http.ListenAndServe(":8080", nil)
     }
    

    Here, we add the handleWebSocket function to handle WebSocket connections on the /ws endpoint.

  2. Save the changes and exit the text editor.

    Now, create a new file called index.html in the project directory and open it in your text editor.

    Add the following code to index.html:

     <!DOCTYPE html>
     <html>
     <head>
     	<title>Chat Application</title>
     	<link rel="stylesheet" type="text/css" href="style.css">
     </head>
     <body>
     	<h1>Chat Application</h1>
        
     	<div id="chat"></div>
        
     	<script>
     		var socket = new WebSocket("ws://" + window.location.host + "/ws");
        
     		socket.onopen = function() {
     			console.log("Connected to server");
     		};
        
     		socket.onmessage = function(event) {
     			console.log("Received message:", event.data);
     		};
        
     		socket.onclose = function() {
     			console.log("Disconnected from server");
     		};
     	</script>
     </body>
     </html>
    

    Here, we define a basic HTML structure with a WebSocket connection to the /ws endpoint.

  3. Save the changes and exit the text editor.

Testing the Application

To test our chat application, follow these steps:

  1. Open your terminal and navigate to the project directory.
  2. Start the web server: go run main.go
  3. Open a web browser and visit http://localhost:8080.
  4. Open the browser’s developer console.

  5. You should see a “Connected to server” message in the console, indicating a successful WebSocket connection.

    Now, let’s test the server-side WebSocket logic.

  6. Open chat.go in your text editor.

    Modify the handleWebSocket function as follows:

     func handleWebSocket(w http.ResponseWriter, r *http.Request) {
     	conn, err := upgrader.Upgrade(w, r, nil)
     	if err != nil {
     		log.Println(err)
     		return
     	}
        
     	for {
     		messageType, message, err := conn.ReadMessage()
     		if err != nil {
     			log.Println(err)
     			return
     		}
        
     		log.Printf("Received message: %s", message)
        
     		// Broadcast the received message to all connected clients
     		err = conn.WriteMessage(messageType, message)
     		if err != nil {
     			log.Println(err)
     			return
     		}
     	}
     }
    

    Here, we read the messages sent by clients, log them, and then broadcast them to all connected clients.

  7. Save the changes and exit the text editor.

    Now, restart the web server: go run main.go

  8. Open multiple browser tabs or windows to http://localhost:8080.
  9. In one tab, type a message in the developer console and press Enter.

  10. You should see the message being logged in all the open tabs.

    Congratulations! You have successfully built a real-time chat application with Go and WebSockets.

Conclusion

In this tutorial, we learned how to create a real-time chat application using Go and WebSockets. We set up a basic web server, implemented WebSocket functionality, and created a chat application that allows users to send and receive messages in real time.

This chat application can be extended further by adding user authentication, persistent storage of chat history, and additional features like emoji support or file sharing.

You can find the complete source code for this tutorial on GitHub: chat-app

Feel free to explore and enhance the chat application according to your needs. Happy coding!