Sling Academy
Home/Golang/Creating a Scalable WebSocket Backend with Goroutines in Go

Creating a Scalable WebSocket Backend with Goroutines in Go

Last updated: November 26, 2024

WebSockets provide a powerful way to facilitate two-way communication channels over a single TCP connection, ideal for building real-time applications. In this article, we’ll explore how to create a scalable WebSocket backend using Go, leveraging the power of goroutines for managing connections efficiently.

Setting Up Your Go Project

Begin by creating a new Go project. Initialize your project and get the required WebSocket package:

mkdir websocket-backend
cd websocket-backend
go mod init websocket-backend
go get github.com/gorilla/websocket

The gorilla/websocket package provides a comprehensive set of tools to work with WebSocket connections in Go.

Handling WebSocket Connections

Create a main package file, main.go, where we’ll set up a basic HTTP server capable of upgrading connections to WebSockets.

package main

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

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

func handleConnections(w http.ResponseWriter, r *http.Request) {
    ws, err := upgrader.Upgrade(w, r, nil)
    if err != nil {
        log.Fatalf("failed to upgrade websocket connection: %v", err)
        return
    }
    defer ws.Close()

    for {
        _, msg, err := ws.ReadMessage()
        if err != nil {
            log.Printf("error reading message: %v", err)
            break
        }
        log.Printf("received message: %s", msg)
        err = ws.WriteMessage(websocket.TextMessage, msg)
        if err != nil {
            log.Printf("error writing message: %v", err)
            break
        }
    }
}

Thecode handleConnections upgrades HTTP connections to WebSockets using the Gorilla WebSocket package. It reads messages from the client and writes them back as a simple echo server.

Launching the Server

Next, let's set up the server to handle incoming requests. We'll define a main function for starting our WebSocket server:

func main() {
    http.HandleFunc("/ws", handleConnections)
    log.Println("Starting WebSocket server on :8080")
    if err := http.ListenAndServe(":8080", nil); err != nil {
        log.Fatalf("failed to start server: %v", err)
    }
}

In the main function, we define an endpoint /ws for WebSocket connections and start the server on port 8080. Building and running this Go program will allow establishing WebSocket communications from clients.

Handling Multiple Connections with Goroutines

For a production-ready application that needs to handle multiple connections simultaneously, we take advantage of Go's concurrency model using goroutines. Modify handleConnections to launch a goroutine for handling each client interaction:

func handleConnections(w http.ResponseWriter, r *http.Request) {
    ws, err := upgrader.Upgrade(w, r, nil)
    if err != nil {
        log.Fatalf("failed to upgrade websocket connection: %v", err)
        return
    }

    go func(ws *websocket.Conn) {
        defer ws.Close()
        for {
            _, msg, err := ws.ReadMessage()
            if err != nil {
                log.Printf("error reading message: %v", err)
                break
            }
            log.Printf("received message: %s", msg)
            err = ws.WriteMessage(websocket.TextMessage, msg)
            if err != nil {
                log.Printf("error writing message: %v", err)
                break
            }
        }
    }(ws)
}

Each new connection is handled in its own goroutine, ensuring the server can scale by managing multiple connections efficiently without blocking.

Conclusion

With the ability to leverage goroutines, Golang provides a robust framework for building scalable WebSocket backends capable of managing numerous simultaneous connections. This basic echo server can be further expanded with features like authentication, message broadcasting, or other application-specific logic to suit your needs.

Next Article: Using WebSockets with Channels for Concurrent Communication in Go

Previous Article: Using WebSockets for Multiplayer Game Development in Go

Series: Websocket & Chat Programs in Go

Golang

Related Articles

You May Also Like

  • How to remove HTML tags in a string in Go
  • How to remove special characters in a string in Go
  • How to remove consecutive whitespace in a string in Go
  • How to count words and characters in a string in Go
  • Relative imports in Go: Tutorial & Examples
  • How to run Python code with Go
  • How to generate slug from title in Go
  • How to create an XML sitemap in Go
  • How to redirect in Go (301, 302, etc)
  • Using Go with MongoDB: CRUD example
  • Auto deploy Go apps with CI/ CD and GitHub Actions
  • Fixing Go error: method redeclared with different receiver type
  • Fixing Go error: copy argument must have slice type
  • Fixing Go error: attempted to use nil slice
  • Fixing Go error: assignment to constant variable
  • Fixing Go error: cannot compare X (type Y) with Z (type W)
  • Fixing Go error: method has pointer receiver, not called with pointer
  • Fixing Go error: assignment mismatch: X variables but Y values
  • Fixing Go error: array index must be non-negative integer constant