...

Websockets in Go: A Simple Master Guide in 4 Steps

Rate this post

Introduction

Websockets in Go is simple and easy to apply. It means It is fun and effortless to apply it using standard packages or third-party packages (e.g. gorilla websockets). Let us first learn about websockets in general, their use cases, and then how to implement them in Go.

What is a websocket?

A WebSocket is a communication protocol that provides full-duplex communication channels over a single TCP connection. It allows for real-time, two-way communication between a client (typically a web browser) and a server. Unlike traditional HTTP, which is request-response-based and stateless, WebSocket connections remain open, enabling continuous data exchange in both directions without the need to re-establish the connection for each message.

Prerequisites

Use-cases of Websockets

WebSockets serve as a go-to solution for applications demanding swift, real-time communication, including:

  • Online Chat Platforms
  • Online Gaming Interfaces
  • Financial Trading Platforms
  • Live Sports Updates
  • Collaborative Tools

Their utilization presents advantages over traditional polling or long-polling methods. WebSockets circumvent the inefficiency of repeatedly initiating connections for each request. This approach diminishes the overhead linked with real-time updates, ensuring faster and more responsive communication channels.

How it works?

To establish a WebSocket connection, a client sends an initial HTTP request with an “Upgrade” header to indicate its intention to switch to the WebSocket protocol. Once the server agrees to the upgrade, the connection is switched to a full-duplex WebSocket connection, and both the client and server can send messages to each other anytime.

Websockets in Go Sequence Diagram

Implementation of Websockets in go

Step 1 – Server-side implementation of Websockets in go

package main

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

// since websockets are fully duplex connections so we can customise 
// buffer size for receive side (ReadBufferSize) and buffer size for send
// side (WriteBufferSize). It is in bytes
var upgrader = websocket.Upgrader{
    ReadBufferSize:  1024, 
    WriteBufferSize: 1024,
}

func handleWebSocketConnection(w http.ResponseWriter, r *http.Request) {
    conn, err := upgrader.Upgrade(w, r, nil)
    if err != nil {
        return
    }
    defer conn.Close() // closing the connection is must otherwise it will cause memory leak

    for {
        messageType, p, err := conn.ReadMessage() // read from client
        if err != nil {
            return
        }

        fmt.Println("Message received from client: ", string(p))
        reply := "from server: " + string(p)
        if err := conn.WriteMessage(messageType, []byte(reply)); err != nil { // send to client
            return
        }
    }
}

func main() {
    http.HandleFunc("/ws", handleWebSocketConnection)
    fmt.Println("Starting websocket server on 8080")
    http.ListenAndServe(":8080", nil)
}

Step 2 – Client-side implementation

package main

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

func main() {
    conn, _, err := websocket.DefaultDialer.Dial("ws://localhost:8080/ws", nil)
    if err != nil {
        log.Fatal(err)
    }
    defer conn.Close()

    message := []byte("Hello, WebSocket!")
    // WriteMessage will write the message to the connection which will be received
    // by server using conn.ReadMessage()
    if err := conn.WriteMessage(websocket.TextMessage, message); err != nil {
        log.Fatal(err)
    }

    // ReadMessage will read the message from the connection which was sent
    // by server using conn.WriteMessage()
    _, p, err := conn.ReadMessage()
    if err != nil {
        log.Fatal(err)
    }
    log.Printf("Received: %s", p)
}

Step 3 – Project Setup

cd to /path/to/workspace. E.g cd ~/workspace/go

Create client and server directory

mkdir client && mkdir server

Initialize server using go mod init. cd server && go mod init websocketserver

Create main.go in server and write server-side code from above

Initialize client using go mod init. cd client && go mod init websocketclient

Create main.go in client and write client-side code from above

Step 4 – Execution

cd server (go inside server directory)

go run main.go (this will pull dependencies, build and run)

Open another terminal

cd client (go inside client directory)

go run main.go (this will pull dependencies, build and run)

Output

// Client Side

Hello, WebSocket!
from server: Hello, WebSocket!

// Server Side
Starting websocket server on 8080
Message received from client: Hello, WebSocket!

Conclusion

In conclusion, WebSockets in Go presents an instrumental technology for building robust, real-time communication channels. Leveraging Go’s native support for WebSockets, developers can craft efficient and responsive applications across various domains. The versatility of WebSockets extends to powering online gaming, chat platforms, financial trading systems, live sports updates, and collaborative tools.

The inherent advantages of WebSockets, including low-latency communication and bidirectional data flow, significantly enhance the user experience in interactive applications. Go’s concurrency model further amplifies these benefits by allowing seamless integration of WebSockets with concurrent operations, ensuring scalable and efficient systems.

WebSockets’ capability to maintain persistent connections, eliminate the overhead of connection establishment for each request, and enable real-time updates solidifies their place as a cornerstone for modern, responsive web applications. Embracing WebSockets in Go not only facilitates responsive and engaging user experiences but also contributes to building high-performing and interactive applications.

Enjoy!!!

Spread the love

Leave a Comment

Seraphinite AcceleratorOptimized by Seraphinite Accelerator
Turns on site high speed to be attractive for people and search engines.