WebSocket in Go: Real-Time Applications from A to Z

Online Python Trainer for Beginners

Learn Python easily without overwhelming theory. Solve practical tasks with automatic checking, get hints in Russian, and write code directly in your browser — no installation required.

Start Course

Introduction to WebSocket in Go: Why Real-Time?



Modern web applications increasingly require instant data delivery. The traditional HTTP request/response model no longer suffices for tasks like chats, online games, stock quotes, and monitoring dashboards. This is where WebSocket comes to the rescue — a protocol that provides a persistent bidirectional connection between client and server. In this article, we will explore how to build real-time applications in Go (Golang) using WebSocket, from setup to production-ready solutions.



Go is ideal for WebSocket thanks to its lightweight concurrency model (goroutines) and high performance. We will progress from a simple echo server to a full-fledged chat and monitoring system.



WebSocket Basics and Environment Setup



What is WebSocket?

WebSocket is a protocol that operates over TCP. It starts with an HTTP handshake (upgrade), after which the connection switches to a persistent bidirectional channel. Unlike HTTP, the server can send data to the client without a request — this is the foundation of real-time communication.



Installation and Libraries

Go does not have a standard library for WebSocket, but there is a popular library gorilla/websocket. Let's install it:

go get github.com/gorilla/websocket


You can also use nhooyr.io/websocket (a more modern alternative), but in this article we will stick with gorilla as the most widely used.



First WebSocket Server in Go

Let's write a simple echo server that receives a message and sends it back:

package main

import ( "log" "net/http" "github.com/gorilla/websocket")

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

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

for { mt, message, err := conn.ReadMessage() if err != nil { log.Println("Read:", err) break } log.Printf("Received: %s", message) err = conn.WriteMessage(mt, message) if err != nil { log.Println("Write:", err) break } }}

func main() { http.HandleFunc("/echo", echoHandler) log.Println("Server started on :8080") log.Fatal(http.ListenAndServe(":8080", nil))}


This is a minimal working example. Note the Upgrader — it checks the HTTP headers and switches the connection.



Real-Time Application Architecture: Chat in Go



Connection Management

For a chat, you need to manage multiple clients. Let's create a Hub structure that will store all active connections and broadcast messages:

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

type Hub struct { clients map[*Client]bool broadcast chan []byte register chan *Client unregister chan *Client}

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 := <-h.register: h.clients[client] = true case client := <-h.unregister: if _, ok := h.clients[client]; ok { delete(h.clients, client) close(client.send) } case message := <-h.broadcast: for client := range h.clients { select { case client.send <- message: default:

Blogs

Book Recommendations