021 Project 21: WebSocket Chat

021 Build a WebSocket Chat Server

A minimal real-time chat backend with broadcast hub.

Setup

go mod init example.com/gochat
go get github.com/gorilla/websocket@latest
clients <-> ws hub <-> broadcast channel

Full main.go

package main

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

    "github.com/gorilla/websocket"
)

var upgrader = websocket.Upgrader{CheckOrigin: func(r *http.Request) bool { return true }}

type hub struct {
    mu      sync.Mutex
    clients map[*websocket.Conn]struct{}
}

func (h *hub) add(c *websocket.Conn) {
    h.mu.Lock(); defer h.mu.Unlock()
    h.clients[c] = struct{}{}
}

func (h *hub) del(c *websocket.Conn) {
    h.mu.Lock(); defer h.mu.Unlock()
    delete(h.clients, c)
}

func (h *hub) broadcast(msg []byte) {
    h.mu.Lock(); defer h.mu.Unlock()
    for c := range h.clients {
        _ = c.WriteMessage(websocket.TextMessage, msg)
    }
}

func main() {
    h := &hub{clients: map[*websocket.Conn]struct{}{}}

    http.HandleFunc("/ws", func(w http.ResponseWriter, r *http.Request) {
        c, err := upgrader.Upgrade(w, r, nil)
        if err != nil {
            return
        }
        h.add(c)
        defer func() { h.del(c); _ = c.Close() }()

        for {
            _, msg, err := c.ReadMessage()
            if err != nil {
                return
            }
            h.broadcast(msg)
        }
    })

    log.Println("ws chat on :8090 /ws")
    log.Fatal(http.ListenAndServe(":8090", nil))
}

Run

go run .
# Connect from browser/websocket client to ws://localhost:8090/ws

Step-by-Step Explanation

  1. Define request and response contracts first.
  2. Validate inbound input before doing any state changes.
  3. Keep handler logic short and move reusable logic into helper functions.
  4. Add timeouts and clear error paths.
  5. Return consistent responses and status codes.

Code Anatomy

  • Handlers parse input, call domain logic, write response.
  • Shared state uses synchronization where needed.
  • Transport concerns stay separate from business rules.

Learning Goals

  • Build reliable service endpoints in Go.
  • Understand API ergonomics and operational safety.
  • Prepare code structure for tests and persistence later.