Golang Fiber框架 - 实时网页开发指南

Golang Fiber框架 - 实时网页开发指南 大家好

想问问是否有人有用 Fiber 构建的交互式/实时(WebSocket)更新网页/示例。

G

1 回复

更多关于Golang Fiber框架 - 实时网页开发指南的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


在Golang Fiber框架中实现实时WebSocket功能,可以使用github.com/gofiber/websocket/v2包。以下是一个完整的实时聊天室示例:

package main

import (
    "log"
    "sync"

    "github.com/gofiber/fiber/v2"
    "github.com/gofiber/fiber/v2/middleware/logger"
    "github.com/gofiber/websocket"
)

type Client struct {
    conn *websocket.Conn
    send chan []byte
}

var (
    clients   = make(map[*Client]bool)
    broadcast = make(chan []byte)
    mu        sync.RWMutex
)

func main() {
    app := fiber.New()
    app.Use(logger.New())

    // WebSocket升级中间件
    app.Use("/ws", func(c *fiber.Ctx) error {
        if websocket.IsWebSocketUpgrade(c) {
            c.Locals("allowed", true)
            return c.Next()
        }
        return fiber.ErrUpgradeRequired
    })

    // WebSocket端点
    app.Get("/ws", websocket.New(func(c *websocket.Conn) {
        client := &Client{
            conn: c,
            send: make(chan []byte, 256),
        }

        mu.Lock()
        clients[client] = true
        mu.Unlock()

        defer func() {
            mu.Lock()
            delete(clients, client)
            mu.Unlock()
            close(client.send)
            c.Close()
        }()

        // 读取消息
        go func() {
            for {
                mt, msg, err := c.ReadMessage()
                if err != nil {
                    break
                }
                if mt == websocket.TextMessage {
                    broadcast <- msg
                }
            }
        }()

        // 写入消息
        for message := range client.send {
            if err := c.WriteMessage(websocket.TextMessage, message); err != nil {
                break
            }
        }
    }))

    // 广播消息处理
    go handleMessages()

    // 静态文件服务(前端页面)
    app.Static("/", "./public")

    log.Fatal(app.Listen(":3000"))
}

func handleMessages() {
    for msg := range broadcast {
        mu.RLock()
        for client := range clients {
            select {
            case client.send <- msg:
            default:
                close(client.send)
                delete(clients, client)
            }
        }
        mu.RUnlock()
    }
}

对应的前端HTML页面(public/index.html):

<!DOCTYPE html>
<html>
<head>
    <title>Fiber WebSocket 实时聊天</title>
    <style>
        #messages { 
            height: 300px; 
            border: 1px solid #ccc; 
            overflow-y: scroll; 
            padding: 10px; 
        }
        #messageInput { 
            width: 80%; 
            padding: 10px; 
        }
    </style>
</head>
<body>
    <h1>Fiber WebSocket 实时聊天室</h1>
    <div id="messages"></div>
    <input type="text" id="messageInput" placeholder="输入消息...">
    <button onclick="sendMessage()">发送</button>

    <script>
        const ws = new WebSocket('ws://localhost:3000/ws');
        const messages = document.getElementById('messages');
        const messageInput = document.getElementById('messageInput');

        ws.onmessage = function(event) {
            const message = document.createElement('div');
            message.textContent = event.data;
            messages.appendChild(message);
            messages.scrollTop = messages.scrollHeight;
        };

        function sendMessage() {
            if (messageInput.value) {
                ws.send(messageInput.value);
                messageInput.value = '';
            }
        }

        messageInput.addEventListener('keypress', function(e) {
            if (e.key === 'Enter') sendMessage();
        });
    </script>
</body>
</html>

实时数据推送示例(股票价格更新):

// 实时股票价格推送
app.Get("/ws/stocks", websocket.New(func(c *websocket.Conn) {
    ticker := time.NewTicker(1 * time.Second)
    defer ticker.Stop()

    for {
        select {
        case <-ticker.C:
            price := generateStockPrice()
            msg := fmt.Sprintf(`{"symbol":"AAPL","price":%.2f}`, price)
            if err := c.WriteMessage(websocket.TextMessage, []byte(msg)); err != nil {
                return
            }
        }
    }
}))

func generateStockPrice() float64 {
    return 150 + rand.Float64()*10
}

实时通知系统示例:

// 用户通知推送
type Notification struct {
    UserID string `json:"user_id"`
    Message string `json:"message"`
}

var userConnections = make(map[string]*websocket.Conn)

app.Get("/ws/notifications/:userID", websocket.New(func(c *websocket.Conn) {
    userID := c.Params("userID")
    userConnections[userID] = c
    
    defer delete(userConnections, userID)
    
    for {
        if _, _, err := c.ReadMessage(); err != nil {
            break
        }
    }
}))

// 发送通知函数
func SendNotification(userID, message string) error {
    if conn, ok := userConnections[userID]; ok {
        notification := Notification{
            UserID:  userID,
            Message: message,
        }
        data, _ := json.Marshal(notification)
        return conn.WriteMessage(websocket.TextMessage, data)
    }
    return nil
}

这些示例展示了Fiber框架中WebSocket的完整实现,包括实时聊天、数据推送和通知系统。

回到顶部