Why Go and WebSockets Are the Perfect Duo for Real-Time?
Imagine a scenario: you launch an online chat, a stock trading terminal, or a multiplayer game. Users expect instant reactions. No one wants to manually refresh the page or wait 5 seconds for a server response. This is where WebSockets come into play.
Go (Golang) is perfectly suited for this task. Its lightweight goroutines allow you to handle tens of thousands of concurrent connections without performance degradation. And the standard net/http library paired with the gorilla/websocket package makes writing real-time applications a pure pleasure.
In this article, we will break down how WebSocket works in Go, write a simple chat, and discuss best practices. Let's go!
What is WebSocket and How Is It Better Than HTTP?
In short, WebSocket is a protocol that establishes a persistent, full-duplex connection between a client (browser) and a server. Unlike classic HTTP, where the client always initiates a request, WebSocket allows the server to send data to the client at any time.
The advantages are obvious:
- Instant delivery — no delays for establishing a new connection.
- Less traffic — headers are sent only once during the handshake.
- Efficiency — one connection instead of thousands of HTTP requests.
Go handles managing these connections excellently. Instead of spawning OS threads (which is expensive), Go uses goroutines. One goroutine — one connection. Thousands of goroutines run on a few OS threads, consuming minimal memory.
Setting Up and Preparing a Go Project
Let's assume you already have Go installed. If not — brew install go or download it from golang.org.
Let's create a new module:
mkdir go-websocket-chatcd go-websocket-chatgo mod init go-websocket-chatNow install the most popular library gorilla/websocket:
go get github.com/gorilla/websocketDone. Now we have everything to build a real-time application in Go.
Writing a WebSocket Server in Go
Let's start with the simplest thing — an echo server. The client sends a message, the server returns it. This will help understand the basic mechanics.
Step 1: Structure and Connection Upgrade
A WebSocket connection starts with an HTTP request (handshake). The server must "upgrade" it to WebSocket. In Go, this is done via http.Hijacker or through the convenient Upgrader method from the gorilla/websocket package.
Create a file main.go:
package main
import ( "fmt" "log" "net/http" "github.com/gorilla/websocket")
var upgrader = websocket.Upgrader{ CheckOrigin: func(r *http.Request) bool { return true // allow any origin (for development) },}
func handleWebSocket(w http.ResponseWriter, r *http.Request) { conn, err := upgrader.Upgrade(w, r, nil) if err != nil { log.Print("Upgrade error:", err) return } defer conn.Close()
// Infinite read and write loop for { messageType, message, err := conn.ReadMessage() if err != nil { log.Println("Read error:", err) break } log.Printf("Received: %s", message)
// Send the same message back err = conn.WriteMessage(messageType, message) if err != nil { log.Println("Write error:", err) break } }}
func main() { http.HandleFunc("/ws", handleWebSocket) fmt.Println("Server started on :8080") log.Fatal(http.ListenAndServe(":8080", nil))}Run it: go run main.go