WebSockets provide a way to exchange data between the server and client through a persistent connection. This article will guide you in building a basic WebSocket server using the Go programming language. Follow along this tutorial to learn how to handle WebSocket connections in a Go server using the golang.org/x/net/websocket package.

Step 1: Setting Up Your Go Environment

Before diving into the code, ensure you have Go installed on your machine. You can download it from the official Go website. After installing, verify your installation by running:

go version

Step 2: Create a Simple Go Web Server

First, create a new directory for your project and navigate into it. Then, create a file named main.go. Let’s start with a simple HTTP server:

package main

import (
    "fmt"
    "net/http"
)

func main() {
    http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
        fmt.Fprintf(w, "Hello, World!")
    })

    fmt.Println("Server starting at http://localhost:8080")
    if err := http.ListenAndServe(":8080", nil); err != nil {
        panic(err)
    }
}

This code will set up a simple HTTP server on port 8080 that responds with "Hello, World!" when accessed.

Step 3: Install the WebSocket Package

To handle WebSocket connections, we need to install the WebSocket package. Run the following command to install it:

go get golang.org/x/net/websocket

Step 4: Implement WebSocket Handling

Let’s enhance our HTTP server to handle WebSocket requests. Update your main.go file with the following code:

package main

import (
    "fmt"
    "net/http"
    "golang.org/x/net/websocket"
)

func websocketHandler(ws *websocket.Conn) {
    var err error
    for {
        var reply string

        if err = websocket.Message.Receive(ws, &reply); err != nil {
            fmt.Println("Can't receive:", err)
            break
        }
        fmt.Printf("Received: %s\n", reply)

        msg := "Received: " + reply
        fmt.Printf("Sending: %s\n", msg)

        if err = websocket.Message.Send(ws, msg); err != nil {
            fmt.Println("Can't send:", err)
            break
        }
    }
}

func main() {
    http.Handle("/websocket", websocket.Handler(websocketHandler))

    fmt.Println("WebSocket server starting at http://localhost:8080")
    if err := http.ListenAndServe(":8080", nil); err != nil {
        panic("ListenAndServe:", err)
    }
}

In the updated code, we define a websocketHandler function to handle incoming WebSocket connections. The WebSocket server listens for messages, appends "Received: " to each message, and sends it back to the client.

Step 5: Testing the WebSocket Server

We need a way to test our WebSocket server. You can use a simple webpage or a tool like websocket.org's Echo Test. Here is an example of an HTML file you can use to test:

<!DOCTYPE html>
<html>
<head>
    <title>WebSocket Test</title>
</head>
<body>
    <script type="text/javascript">
        var ws = new WebSocket("ws://localhost:8080/websocket");
        ws.onopen = function() {
            console.log("Connection opened...");
            ws.send("Hello Server!");
        };
        
        ws.onmessage = function(evt) {
            console.log("Message Received: " + evt.data);
            ws.close();
        };
        
        ws.onclose = function() {
            console.log("Connection closed...");
        };
    </script>
</body>
</html>

Save this HTML code to a file and open it in a web browser while your Go server is running. This script will connect to the server, send a message, and log the responses in the console.

Conclusion

In this article, we walked through setting up a simple WebSocket server using Go. By implementing the steps above, you can create the foundation for building real-time applications with Go. There are many additional features and production-level concerns like proper error handling, security, and message structure that you can explore to enhance your WebSocket server.