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