Table of Contents
- Introduction
- Prerequisites - Go Installation - WebSocket
- Setting Up the Project
-
Building the Server - Creating a WebSocket Server - Handling WebSocket Connections - Broadcasting Messages
- Building the Client - Creating a WebSocket Connection - Sending and Receiving Messages
- Testing the App
- Conclusion
Introduction
In this tutorial, we will build a real-time collaboration app using Go and WebSocket. The app will allow multiple users to connect to a server and collaborate in real-time by sending messages to each other. By the end of this tutorial, you will have a basic understanding of how to set up a WebSocket server and client using Go, and how to handle real-time data communication.
Prerequisites
Before you begin, ensure that you have the following prerequisites:
- Basic knowledge of Go programming language
- Go installed on your machine
- Familiarity with the concept of WebSockets
Go Installation
To install Go, follow these steps:
- Visit the official Go website at https://golang.org.
- Download the installer suitable for your operating system.
-
Run the installer and follow the instructions to complete the installation.
-
Verify the installation by opening a terminal or command prompt and running the following command:
go version
If the installation was successful, it should display the installed Go version.
WebSocket
WebSockets provide a bi-directional communication channel between a server and client over a single, long-lived connection. It allows real-time data transfer and is widely used for building real-time applications such as chat systems, collaborative editing tools, and more. WebSocket communication is based on the WebSocket protocol, which is built on top of the HTTP protocol.
Setting Up the Project
To begin, create a new directory for your project. Open a terminal or command prompt and navigate to the desired location. Once there, execute the following command to create a new folder:
mkdir real-time-collab-app
Navigate into the project folder:
cd real-time-collab-app
Now, initialize a Go module for your project:
go mod init github.com/your-username/real-time-collab-app
This command will create a go.mod
file that will track your project’s dependencies.
Building the Server
Let’s start by building the server-side logic using Go. Create a new file called server.go
in your project folder.
Creating a WebSocket Server
In server.go
, add the following code:
package main
import (
"log"
"net/http"
"github.com/gorilla/websocket"
)
var clients = make(map[*websocket.Conn]bool)
var broadcast = make(chan Message)
// Message struct for incoming and outgoing messages.
type Message struct {
Username string `json:"username"`
Content string `json:"content"`
}
func main() {
// Configure WebSocket route
http.HandleFunc("/ws", handleConnections)
// Start listening for incoming chat messages
go handleMessages()
// Start the server on localhost:8000
log.Println("Server started on :8000")
err := http.ListenAndServe(":8000", nil)
if err != nil {
log.Fatal("ListenAndServe: ", err)
}
}
func handleConnections(w http.ResponseWriter, r *http.Request) {
// Upgrade initial GET request to WebSocket
upgrader := websocket.Upgrader{}
conn, err := upgrader.Upgrade(w, r, nil)
if err != nil {
log.Fatal(err)
}
// Close the connection on exit
defer conn.Close()
// Register new client
clients[conn] = true
for {
var msg Message
// Read in new message
err := conn.ReadJSON(&msg)
if err != nil {
log.Printf("error: %v", err)
delete(clients, conn)
break
}
// Send the newly received message to the broadcast channel
broadcast <- msg
}
}
In this code, we import the necessary packages such as log
, net/http
, and github.com/gorilla/websocket
. We define two global variables; clients
, a map to store all connected clients, and broadcast
, a channel to broadcast messages to all connected clients.
The Message
struct defines the structure of the incoming and outgoing messages. The main
function sets up the WebSocket route, starts a goroutine to handle incoming messages, and starts the server on localhost:8000
.
The handleConnections
function is responsible for upgrading the initial HTTP request to a WebSocket connection. It registers the new client in the clients
map and listens for incoming messages. Once a message is received, it is sent to the broadcast
channel.
Handling WebSocket Connections
Next, add the following code to server.go
:
func handleMessages() {
for {
// Get the next message from the broadcast channel
msg := <-broadcast
// Send the message to all connected clients
for client := range clients {
err := client.WriteJSON(msg)
if err != nil {
log.Printf("error: %v", err)
client.Close()
delete(clients, client)
}
}
}
}
The handleMessages
function listens for messages on the broadcast
channel. Whenever a new message is received, it iterates over all connected clients and sends the message using the WriteJSON
method. If any error occurs while sending the message, the client is closed and removed from the clients
map.
Broadcasting Messages
Finally, let’s add a WebSocket endpoint in server.go
to serve the HTML page for the client. You’ll also need to import the html/template
package at the top of the file:
import (
// ...
"html/template"
)
// HomeHandler serves the home HTML page
func HomeHandler(w http.ResponseWriter, r *http.Request) {
homeTemplate := template.Must(template.ParseFiles("index.html"))
homeTemplate.Execute(w, nil)
}
func main() {
// ...
// Configure other HTTP routes
http.HandleFunc("/", HomeHandler)
// ...
}
Here, we define the HomeHandler
function to serve the index.html
file using the template
package. In the main
function, we configure the root /
route to use this handler.
Building the Client
Now that we have the server logic in place, let’s create the client-side JavaScript code to establish a WebSocket connection and handle messages.
Create a new file called index.html
in your project folder with the following contents:
<!DOCTYPE html>
<html>
<head>
<title>Real-Time Collaboration</title>
<script src="https://cdn.jsdelivr.net/npm/vue"></script>
</head>
<body>
<div id="app">
<h1>Real-Time Collaboration</h1>
<div>
<input v-model="message" @keyup.enter="sendMessage" placeholder="Enter a message">
</div>
<ul>
<li v-for="msg in messages">
<strong>{{ msg.username }}</strong>: {{ msg.content }}
</li>
</ul>
</div>
<script>
const webSocket = new WebSocket("ws://localhost:8000/ws");
const app = new Vue({
el: '#app',
data: {
message: "",
messages: [],
},
methods: {
sendMessage: function () {
webSocket.send(JSON.stringify({
username: "User",
content: this.message,
}));
this.message = "";
},
},
});
webSocket.onmessage = function (event) {
const msg = JSON.parse(event.data);
app.messages.push(msg);
};
</script>
</body>
</html>
In this HTML file, we import the Vue.js framework and set up a basic UI for the collaboration app. It includes an input field to enter messages and a list to display received messages.
We create a WebSocket connection using the WebSocket
object and define a Vue instance to handle sending and receiving messages. When the user enters a message, it is sent to the server as a JSON string. The received messages are parsed and added to the messages
array, which will automatically update the UI.
Testing the App
To test the app, open two separate terminals or command prompts. In the first one, navigate to the project folder and start the server by running:
go run server.go
You should see the server started message in the console.
In the second terminal, navigate to the project folder and open the HTML file in a web browser:
open index.html
This will open the collaboration app in your default browser. Enter a message in the input field and press Enter. You should see the message appear in the list, indicating successful communication between the client and server.
To test real-time collaboration, open the same HTML file in another browser window or tab. Enter messages in one window and observe them appearing in real-time on the other window.
Congratulations! You have built a real-time collaboration app using Go and WebSockets.
Conclusion
In this tutorial, you learned how to build a real-time collaboration app using Go and WebSockets. You set up a WebSocket server in Go, handled WebSocket connections, and broadcasted messages to all connected clients. On the client-side, you used Vue.js to establish a WebSocket connection, send messages, and display received messages in real-time.
Feel free to explore and enhance the app further by adding features such as user authentication, message history, or additional collaboration capabilities.
Have fun building real-time applications with Go and WebSockets!