Golang WebSocket Example: A Comprehensive Guide

WebSocket is a protocol that enables real-time communication between a client and a server. It allows for bidirectional communication, which means that both the client and the server can send and receive data at any time. Go is a modern programming language that has gained a lot of popularity in recent years due to its simplicity, speed, and ease of use. In this article, we will explore how to implement a WebSocket server in Go and create a WebSocket client using a practical example.

What is WebSocket?

WebSocket is a protocol that enables real-time communication between a client and a server. It was standardized by the World Wide Web Consortium (W3C) in 2011 and has since become widely used in web applications. WebSocket provides a full-duplex communication channel between a client and a server, which means that both parties can send and receive data at any time.

Why use WebSocket?

WebSocket is a great protocol for real-time communication because it provides low latency and high throughput. This makes it ideal for applications that require real-time updates or live data streaming, such as chat applications, online games, and financial trading platforms. WebSocket also reduces the overhead of HTTP requests and responses, which can improve the performance of web applications.

Creating a WebSocket Server in Go

To create a WebSocket server in Go, we will use the Gorilla WebSocket library. This library provides a simple and flexible API for creating WebSocket servers and clients. Here is an example of how to create a WebSocket server in Go using the Gorilla WebSocket library:

“`gopackage main

import (“log””net/http”

“github.com/gorilla/websocket“)

var upgrader = websocket.Upgrader{ReadBufferSize:1024,WriteBufferSize: 1024,}

func main() {http.HandleFunc(“/ws”, handleWebSocket)log.Fatal(http.ListenAndServe(“:8080”, nil))}

func handleWebSocket(w http.ResponseWriter, r *http.Request) {conn, err := upgrader.Upgrade(w, r, nil)if err != nil {log.Println(err)return}defer conn.Close()

for {// Read message from the client_, message, err := conn.ReadMessage()if err != nil {log.Println(err)return}

// Print the message to the consolelog.Printf(“Received message: %s\n”, message)

// Send the message back to the clienterr = conn.WriteMessage(websocket.TextMessage, message)if err != nil {log.Println(err)return}}}“`

Let’s break down this code into its individual components and explain how it works.

Importing the Required Packages

The first step in creating a WebSocket server in Go is to import the required packages. In this example, we are using the “net/http” package to handle HTTP requests and responses, and the “github.com/gorilla/websocket” package to create the WebSocket server.

“`gopackage main

import (“log””net/http”

“github.com/gorilla/websocket”)“`

Creating the Upgrader

The next step is to create an instance of the “websocket.Upgrader” struct. This struct is used to upgrade an HTTP connection to a WebSocket connection. In this example, we are setting the read and write buffer sizes to 1024 bytes.

“`govar upgrader = websocket.Upgrader{ReadBufferSize:1024,WriteBufferSize: 1024,}“`

Defining the Main Function

The main function is the entry point of our program. In this example, we are defining a function called “main” that registers a handler function for the “/ws” route and starts an HTTP server on port 8080.

“`gofunc main() {http.HandleFunc(“/ws”, handleWebSocket)log.Fatal(http.ListenAndServe(“:8080”, nil))}“`

Handling WebSocket Connections

The “handleWebSocket” function is the heart of our WebSocket server. It is called whenever a client connects to the “/ws” route. The “upgrader” struct is used to upgrade the HTTP connection to a WebSocket connection. Once the connection is established, the function enters into an infinite loop that reads messages from the client and sends them back.

“`gofunc handleWebSocket(w http.ResponseWriter, r *http.Request) {conn, err := upgrader.Upgrade(w, r, nil)if err != nil {log.Println(err)return}defer conn.Close()

for {// Read message from the client_, message, err := conn.ReadMessage()if err != nil {log.Println(err)return}

// Print the message to the consolelog.Printf(“Received message: %s\n”, message)

// Send the message back to the clienterr = conn.WriteMessage(websocket.TextMessage, message)if err != nil {log.Println(err)return}}}“`

Creating a WebSocket Client in Go

Now that we have created a WebSocket server in Go, let’s create a WebSocket client that can connect to it. Here is an example of how to create a WebSocket client in Go using the Gorilla WebSocket library:

“`gopackage main

import (“fmt””log””net/url””os””os/signal””time”

“github.com/gorilla/websocket”)

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

u := url.URL{Scheme: “ws”, Host: “localhost:8080”, Path: “/ws”}log.Printf(“connecting to %s”, u.String())

c, _, err := websocket.DefaultDialer.Dial(u.String(), nil)if err != nil {log.Fatal(“dial:”, err)}defer c.Close()

done := make(chan struct{})go func() {defer close(done)for {_, message, err := c.ReadMessage()if err != nil {log.Println(“read:”, err)return}log.Printf(“received: %s”, message)}}()

ticker := time.NewTicker(time.Second)defer ticker.Stop()

for {select {case <-done:returncase t := <-ticker.C:err := c.WriteMessage(websocket.TextMessage, []byte(t.String()))if err != nil {log.Println("write:", err)return}case <-interrupt:log.Println("interrupt")err := c.WriteMessage(websocket.CloseMessage, websocket.FormatCloseMessage(websocket.CloseNormalClosure, ""))if err != nil {log.Println("write close:", err)return}select {case <-done:case <-time.After(time.Second):}return}}}```

Let’s break down this code into its individual components and explain how it works.

Importing the Required Packages

The first step in creating a WebSocket client in Go is to import the required packages. In this example, we are using the “log”, “net/url”, “os”, “os/signal”, “time”, and “github.com/gorilla/websocket” packages.

“`gopackage main

import (“fmt””log””net/url””os””os/signal””time”

“github.com/gorilla/websocket”)“`

Connecting to the WebSocket Server

The next step is to connect to the WebSocket server. In this example, we are using the “websocket.DefaultDialer.Dial” function to establish a WebSocket connection to the server.

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

u := url.URL{Scheme: “ws”, Host: “localhost:8080”, Path: “/ws”}log.Printf(“connecting to %s”, u.String())

c, _, err := websocket.DefaultDialer.Dial(u.String(), nil)if err != nil {log.Fatal(“dial:”, err)}defer c.Close()“`

Handling WebSocket Messages

Once the WebSocket connection is established, we need to handle incoming and outgoing messages. In this example, we are creating a separate goroutine that reads incoming messages and prints them to the console. We are also using a ticker to send a message to the server every second.

“`godone := make(chan struct{})go func() {defer close(done)for {_, message, err := c.ReadMessage()if err != nil {log.Println(“read:”, err)return}log.Printf(“received: %s”, message)}}()

ticker := time.NewTicker(time.Second)defer ticker.Stop()

for {select {case <-done:returncase t := <-ticker.C:err := c.WriteMessage(websocket.TextMessage, []byte(t.String()))if err != nil {log.Println("write:", err)return}case <-interrupt:log.Println("interrupt")err := c.WriteMessage(websocket.CloseMessage, websocket.FormatCloseMessage(websocket.CloseNormalClosure, ""))if err != nil {log.Println("write close:", err)return}select {case <-done:case <-time.After(time.Second):}return}}```

FAQ

What is the Gorilla WebSocket library?

The Gorilla WebSocket library is a popular WebSocket library for Go. It provides a simple and flexible API for creating WebSocket servers and clients.

What are some use cases for WebSocket?

WebSocket is commonly used in web applications that require real-time updates or live data streaming, such as chat applications, online games, and financial trading platforms.

What are some advantages of using WebSocket?

WebSocket provides low latency and high throughput, which makes it ideal for real-time communication. It also reduces the overhead of HTTP requests and responses, which can improve the performance of web applications.