Houd me in de gaten bij het implementeren van WebSocket-communicatie in mijn Go-toepassing.
description
Door deze gids te volgen, verbeter je de interactiviteit en responsiviteit van je toepassing, waardoor realtime gegevensuitwisseling mogelijk wordt zonder voortdurend te hoeven polsen.
prompt
try_prompt
Help me bij het opzetten van WebSocket-communicatie in mijn Go-toepassing. Leg uit hoe je een WebSocket-server opzet, verbindingen beheert en berichte ... more
generate_helper
...
tags
ai_answers
provider: openai
model: gpt-4.1-nano
Natuurlijk! Hier is een overzicht en voorbeeldcode voor het opzetten van een WebSocket-server in Go, inclusief het beheren van verbindingen en het verzenden/ontvangen van berichten voor een eenvoudige chattoepassing.
### 1. Vereisten
Gebruik de populaire `gorilla/websocket` bibliotheek voor WebSocket-functionaliteit:
```bash
go get github.com/gorilla/websocket
```
### 2. WebSocket-server opzetten
Hier is een basisstructuur voor een WebSocket-chatserver:
```go
package main
import (
"fmt"
"log"
"net/http"
"sync"
"github.com/gorilla/websocket"
)
// Client vertegenwoordigt een verbonden client
type Client struct {
conn *websocket.Conn
send chan []byte
}
// Hub beheert alle clients en broadcast
type Hub struct {
clients map[*Client]bool
broadcast chan []byte
register chan *Client
unregister chan *Client
mu sync.Mutex
}
var upgrader = websocket.Upgrader{
ReadBufferSize: 1024,
WriteBufferSize: 1024,
CheckOrigin: func(r *http.Request) bool {
return true // Toevallig, in productie zou je dit beter beveiligen
},
}
func newHub() *Hub {
return &Hub{
clients: make(map[*Client]bool),
broadcast: make(chan []byte),
register: make(chan *Client),
unregister: make(chan *Client),
}
}
func (h *Hub) run() {
for {
select {
case client := <-h.register:
h.mu.Lock()
h.clients[client] = true
h.mu.Unlock()
case client := <-h.unregister:
h.mu.Lock()
if _, ok := h.clients[client]; ok {
delete(h.clients, client)
close(client.send)
}
h.mu.Unlock()
case message := <-h.broadcast:
h.mu.Lock()
for client := range h.clients {
select {
case client.send <- message:
default:
close(client.send)
delete(h.clients, client)
}
}
h.mu.Unlock()
}
}
}
func handleConnections(h *Hub, w http.ResponseWriter, r *http.Request) {
conn, err := upgrader.Upgrade(w, r, nil)
if err != nil {
log.Println("Upgrade fout:", err)
return
}
client := &Client{conn: conn, send: make(chan []byte)}
h.register <- client
go client.writePump()
client.readPump(h)
}
func (c *Client) readPump(h *Hub) {
defer func() {
h.unregister <- c
c.conn.Close()
}()
for {
_, message, err := c.conn.ReadMessage()
if err != nil {
log.Println("Read fout:", err)
break
}
h.broadcast <- message
}
}
func (c *Client) writePump() {
for msg := range c.send {
err := c.conn.WriteMessage(websocket.TextMessage, msg)
if err != nil {
log.Println("Schrijven fout:", err)
c.conn.Close()
break
}
}
}
func main() {
h := newHub()
go h.run()
http.HandleFunc("/ws", func(w http.ResponseWriter, r *http.Request) {
handleConnections(h, w, r)
})
fmt.Println("Server gestart op :8080")
err := http.ListenAndServe(":8080", nil)
if err != nil {
log.Fatal("Server fout:", err)
}
}
```
### 3. Client-side voorbeeld (HTML + JavaScript)
Voor het testen kun je deze eenvoudige client gebruiken:
```html
<!DOCTYPE html>
<html lang="nl">
<head>
<meta charset="UTF-8" />
<title>WebSocket Chat</title>
<script>
let socket;
function init() {
socket = new WebSocket("ws://localhost:8080/ws");
socket.onmessage = function(event) {
const chat = document.getElementById("chat");
chat.value += event.data + "\n";
};
}
function sendMessage() {
const input = document.getElementById("message");
socket.send(input.value);
input.value = "";
}
window.onload = init;
</script>
</head>
<body>
<h2>WebSocket Chat</h2>
<textarea id="chat" rows="20" cols="50" readonly></textarea><br />
<input type="text" id="message" />
<button onclick="sendMessage()">Verzend</button>
</body>
</html>
```
### Samenvatting
- De server gebruikt een `Hub` om alle verbonden clients te beheren en berichten te broadcasten.
- Elke client verbindt via `/ws`.
- Berichten die door een client worden verzonden, worden via de `broadcast` kanaal naar alle verbonden clients gestuurd.
- De client toont berichten in een tekstvak en verzendt berichten via een invoerveld.
Met deze opzet heb je een eenvoudige, realtime chattoepassing met WebSocket in Go!
provider: deepseek
model: deepseek-chat
Ik help je graag met het opzetten van WebSocket-communicatie in Go voor een chattoepassing. Hier is een complete uitleg met voorbeeldcode.
## 1. WebSocket Server Setup
Eerst installeren we de benodigde package:
```bash
go get github.com/gorilla/websocket
```
### Basis WebSocket Server
```go
package main
import (
"fmt"
"log"
"net/http"
"github.com/gorilla/websocket"
)
// Upgrade de HTTP verbinding naar WebSocket
var upgrader = websocket.Upgrader{
CheckOrigin: func(r *http.Request) bool {
return true // In productie moet je dit beperken tot specifieke origins
},
}
// Client vertegenwoordigt een verbonden gebruiker
type Client struct {
conn *websocket.Conn
send chan []byte
}
// Hub beheert alle verbonden clients
type Hub struct {
clients map[*Client]bool
broadcast chan []byte
register chan *Client
unregister chan *Client
}
// Nieuwe Hub initialiseren
func newHub() *Hub {
return &Hub{
broadcast: make(chan []byte),
register: make(chan *Client),
unregister: make(chan *Client),
clients: make(map[*Client]bool),
}
}
// Hub laten draaien
func (h *Hub) run() {
for {
select {
case client := <-h.register:
h.clients[client] = true
fmt.Println("Nieuwe client verbonden")
case client := <-h.unregister:
if _, ok := h.clients[client]; ok {
delete(h.clients, client)
close(client.send)
fmt.Println("Client verbinding verbroken")
}
case message := <-h.broadcast:
for client := range h.clients {
select {
case client.send <- message:
default:
close(client.send)
delete(h.clients, client)
}
}
}
}
}
```
## 2. Client Management
```go
// Client lezen en schrijven
func (c *Client) readPump(hub *Hub) {
defer func() {
hub.unregister <- c
c.conn.Close()
}()
for {
_, message, err := c.conn.ReadMessage()
if err != nil {
if websocket.IsUnexpectedCloseError(err, websocket.CloseGoingAway, websocket.CloseAbnormalClosure) {
log.Printf("error: %v", err)
}
break
}
// Broadcast bericht naar alle clients
hub.broadcast <- message
// Log het ontvangen bericht
fmt.Printf("Bericht ontvangen: %s\n", string(message))
}
}
func (c *Client) writePump() {
defer func() {
c.conn.Close()
}()
for {
select {
case message, ok := <-c.send:
if !ok {
// Hub sluit het kanaal
c.conn.WriteMessage(websocket.CloseMessage, []byte{})
return
}
err := c.conn.WriteMessage(websocket.TextMessage, message)
if err != nil {
log.Printf("Schrijffout: %v", err)
return
}
}
}
}
```
## 3. HTTP Handler voor WebSocket
```go
// WebSocket endpoint handler
func serveWs(hub *Hub, w http.ResponseWriter, r *http.Request) {
conn, err := upgrader.Upgrade(w, r, nil)
if err != nil {
log.Println(err)
return
}
client := &Client{
conn: conn,
send: make(chan []byte, 256),
}
hub.register <- client
// Start goroutines voor lezen en schrijven
go client.writePump()
go client.readPump(hub)
}
// Serveer statische bestanden (HTML, JS, CSS)
func serveHome(w http.ResponseWriter, r *http.Request) {
if r.URL.Path != "/" {
http.Error(w, "Niet gevonden", http.StatusNotFound)
return
}
if r.Method != "GET" {
http.Error(w, "Method niet toegestaan", http.StatusMethodNotAllowed)
return
}
http.ServeFile(w, r, "home.html")
}
```
## 4. HTML Client Interface
Maak een `home.html` bestand:
```html
<!DOCTYPE html>
<html>
<head>
<title>Go WebSocket Chat</title>
<style>
body { font-family: Arial, sans-serif; margin: 20px; }
#chat { width: 500px; height: 300px; border: 1px solid #ccc; padding: 10px; overflow-y: scroll; margin-bottom: 10px; }
#message { width: 400px; padding: 5px; }
button { padding: 5px 15px; }
.message { margin: 5px 0; padding: 5px; background: #f0f0f0; border-radius: 5px; }
.system { color: #666; font-style: italic; }
</style>
</head>
<body>
<h1>Go WebSocket Chat</h1>
<div id="chat"></div>
<input type="text" id="message" placeholder="Typ je bericht...">
<button onclick="sendMessage()">Versturen</button>
<script>
let ws = new WebSocket("ws://localhost:8080/ws");
ws.onopen = function() {
addMessage("Verbonden met de server", "system");
};
ws.onmessage = function(event) {
addMessage(event.data);
};
ws.onclose = function() {
addMessage("Verbinding verbroken", "system");
};
function addMessage(message, type = "user") {
const chat = document.getElementById("chat");
const messageDiv = document.createElement("div");
messageDiv.className = type === "system" ? "message system" : "message";
messageDiv.textContent = message;
chat.appendChild(messageDiv);
chat.scrollTop = chat.scrollHeight;
}
function sendMessage() {
const input = document.getElementById("message");
const message = input.value.trim();
if (message && ws.readyState === WebSocket.OPEN) {
ws.send(message);
input.value = "";
}
}
// Enter toets ondersteuning
document.getElementById("message").addEventListener("keypress", function(e) {
if (e.key === "Enter") {
sendMessage();
}
});
</script>
</body>
</html>
```
## 5. Hoofdapplicatie
```go
package main
import (
"log"
"net/http"
)
func main() {
hub := newHub()
go hub.run()
// HTTP routes
http.HandleFunc("/", serveHome)
http.HandleFunc("/ws", func(w http.ResponseWriter, r *http.Request) {
serveWs(hub, w, r)
})
// Start server
log.Println("Server gestart op http://localhost:8080")
err := http.ListenAndServe(":8080", nil)
if err != nil {
log.Fatal("ListenAndServe: ", err)
}
}
```
## 6. Uitgebreide Chat Functionaliteit
Voor een completere chat-applicatie kun je JSON berichten gebruiken:
```go
// Bericht structuur voor JSON communicatie
type Message struct {
Username string `json:"username"`
Content string `json:"content"`
Type string `json:"type"` // "message", "join", "leave"
Time string `json:"time"`
}
// In de readPump functie:
func (c *Client) readPump(hub *Hub) {
// ... bestaande code ...
for {
var msg Message
err := c.conn.ReadJSON(&msg)
if err != nil {
break
}
// Verwerk het bericht op basis van type
switch msg.Type {
case "join":
fmt.Printf("Gebruiker %s is toegetreden\n", msg.Username)
case "message":
fmt.Printf("Bericht van %s: %s\n", msg.Username, msg.Content)
}
// Broadcast naar alle clients
hub.broadcastJSON(msg)
}
}
```
## Gebruik:
1. Sla alle code op in een directory
2. Voer `go mod init chat-app` uit
3. Voer `go get github.com/gorilla/websocket` uit
4. Start de server: `go run main.go hub.go client.go`
5. Open `http://localhost:8080` in meerdere browser tabbladen om te testen
Deze implementatie biedt:
- Real-time berichtenuitwisseling
- Automatische verbindingsbeheer
- Schaalbaar client management
- Foutafhandeling
- Eenvoudige frontend interface
Je kunt dit verder uitbreiden met gebruikersauthenticatie, berichtgeschiedenis, kamers, en meer geavanceerde functies.

