How to Build a Real-Time Chat Application in Go

Web
Build a real-time chat application in Go by leveraging the `net/http` package for HTTP/WebSocket upgrades and the `gorilla/websocket` library to manage persistent, full-duplex connections between clients and a central server.

Build a real-time chat application in Go by leveraging the net/http package for HTTP/WebSocket upgrades and the gorilla/websocket library to manage persistent, full-duplex connections between clients and a central server. The core architecture involves a hub that broadcasts messages to all connected clients while maintaining a slice of active connections for efficient message distribution.

Here is a minimal, working example using the standard library for the server and gorilla/websocket for the client-side upgrade:

server.go

package main

import (
	"log"
	"net/http"
	"sync"

	"github.com/gorilla/websocket"
)

var (
	upgrader = websocket.Upgrader{
		ReadBufferSize:  1024,
		WriteBufferSize: 1024,
		CheckOrigin: func(r *http.Request) bool { return true },
	}
	clients = make(map[*websocket.Conn]bool)
	mu      sync.Mutex
)

func handleConnections(w http.ResponseWriter, r *http.Request) {
	conn, err := upgrader.Upgrade(w, r, nil)
	if err != nil {
		log.Println(err)
		return
	}
	defer conn.Close()

	mu.Lock()
	clients[conn] = true
	mu.Unlock()
	defer func() {
		mu.Lock()
		delete(clients, conn)
		mu.Unlock()
	}()

	for {
		_, message, err := conn.ReadMessage()
		if err != nil {
			break
		}
		broadcast(message)
	}
}

func broadcast(message []byte) {
	mu.Lock()
	defer mu.Unlock()
	for client := range clients {
		if err := client.WriteMessage(websocket.TextMessage, message); err != nil {
			client.Close()
		}
	}
}

func main() {
	http.HandleFunc("/ws", handleConnections)
	log.Println("Server starting on :8080")
	http.ListenAndServe(":8080", nil)
}

client.html

<script>
  const socket = new WebSocket("ws://localhost:8080/ws");
  socket.onmessage = function(event) {
    console.log("Received: " + event.data);
  };
  socket.onopen = function() {
    socket.send("Hello from client!");
  };
</script>

Run the server with go run server.go. This setup handles the WebSocket handshake, maintains a thread-safe map of active connections, and broadcasts incoming messages to all connected peers immediately. For production, you should add authentication, rate limiting, and a persistent message store (like Redis or a database) to handle history and scale beyond a single process.