WebSockets Basics
WebSockets Basics
Overview
WebSockets upgrade an HTTP connection to a long-lived bidirectional channel. In Go, use golang.org/x/net/websocket (older) or the popular github.com/gorilla/websocket / nhooyr.io/websocket. This chapter shows a minimal gorilla-style echo and operational pitfalls.
Upgrade sketch (gorilla)
go get github.com/gorilla/websocket@latestvar upgrader = websocket.Upgrader{
CheckOrigin: func(r *http.Request) bool {
// tighten in production
return true
},
ReadBufferSize: 1024,
WriteBufferSize: 1024,
}
func echoWS(w http.ResponseWriter, r *http.Request) {
c, err := upgrader.Upgrade(w, r, nil)
if err != nil {
return
}
defer c.Close()
for {
mt, msg, err := c.ReadMessage()
if err != nil {
break
}
if err := c.WriteMessage(mt, msg); err != nil {
break
}
}
}Heartbeats
Idle proxies kill quiet connections. Send pings:
c.SetReadDeadline(time.Now().Add(60 * time.Second))
c.SetPongHandler(func(string) error {
c.SetReadDeadline(time.Now().Add(60 * time.Second))
return nil
})
// writer goroutine: c.WriteControl(websocket.PingMessage, ...)Concurrency
One reader goroutine; one writer goroutine; never concurrent writers without a mutex or dedicated write pump.
read loop → app → write pump (single)
Auth
Authenticate on the HTTP upgrade (cookie/session or Sec-WebSocket-Protocol / query token). Don’t invent a second weak auth after upgrade without TLS.
When not to use WebSockets
| Prefer WS | Prefer HTTP/SSE |
|---|---|
| True bidirectional chat/games | Server→client events only (SSE) |
| Low-latency duplex | Simple request/response |
Rules of thumb
| Do | Don’t |
|---|---|
| Limit message size | Read unbounded frames |
| Ping/pong deadlines | Assume connections live forever |
| Serialize writes | Write from many goroutines bare |
Try next
- Echo server + browser
WebSocketclient.
- Reject oversized messages.
- Broadcast hub with register/unregister channels.