WebSocket in Go

WebSocket Magic in Go

For those seeking to harness the power of WebSockets in Go, the “github.com/gorilla/websocket” package is a force to be reckoned with. Let’s dive into crafting a simple WebSocket library in Go, and sprinkle it with some explanatory goodness in your signature style.

Installation

First and foremost, we’ll need to grab the Gorilla WebSocket package. This can be accomplished with the following command:

go get github.com/gorilla/websocket

A Basic WebSocket Server

Let’s kick things off with a simple WebSocket server. Our server will listen for incoming connections, upgrade them to WebSocket, and then echo messages back to the clients.

package main

import (
	"fmt"
	"net/http"

	"github.com/gorilla/websocket"
)

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

func handleConnections(w http.ResponseWriter, r *http.Request) {
	// Upgrading to WebSocket
	conn, err := upgrader.Upgrade(w, r, nil)
	if err != nil {
		fmt.Printf("Failed to upgrade: %v\n", err)
		return
	}
	defer conn.Close()

	// Echoing messages
	for {
		msgType, msg, err := conn.ReadMessage()
		if err != nil {
			fmt.Printf("Error reading message: %v\n", err)
			break
		}
		fmt.Printf("Received: %s\n", msg)
		err = conn.WriteMessage(msgType, msg)
		if err != nil {
			fmt.Printf("Error writing message: %v\n", err)
			break
		}
	}
}

func main() {
	http.HandleFunc("/ws", handleConnections)
	fmt.Println("WebSocket server running on :8080")
	http.ListenAndServe(":8080", nil)
}

Our server is now primed and ready to echo messages from incoming connections. But what’s a server without a client?

A Simple WebSocket Client

Next up, let’s create a basic WebSocket client that connects to our server and sends a “Hello, WebSocket!” message.

package main

import (
	"fmt"
	"github.com/gorilla/websocket"
	"log"
	"os"
	"os/signal"
)

var addr = "localhost:8080"

func main() {
	interrupt := make(chan os.Signal, 1)
	signal.Notify(interrupt, os.Interrupt)

	// Connecting to WebSocket server
	conn, _, err := websocket.DefaultDialer.Dial("ws://"+addr+"/ws", nil)
	if err != nil {
		log.Fatal("dial:", err)
	}
	defer conn.Close()

	done := make(chan struct{})

	// Receiving messages
	go func() {
		defer close(done)
		for {
			_, msg, err := conn.ReadMessage()
			if err != nil {
				fmt.Println("Error receiving message:", err)
				return
			}
			fmt.Printf("Received: %s\n", msg)
		}
	}()

	// Sending a message
	err = conn.WriteMessage(websocket.TextMessage, []byte("Hello, WebSocket!"))
	if err != nil {
		fmt.Println("Error sending message:", err)
		return
	}

	// Graceful shutdown
	<-interrupt
	err = conn.WriteMessage(websocket.CloseMessage, websocket.FormatCloseMessage(websocket.CloseNormalClosure, ""))
	if err != nil {
		fmt.Println("Error closing message:", err)
		return
	}
	<-done
}

The Grand Finale

And there you have it! A basic WebSocket library in Go