package websocket import ( "encoding/json" "log" "sync" "github.com/gorilla/websocket" ) type client struct { conn *websocket.Conn send chan []byte mu sync.Mutex } type Hub struct { mu sync.RWMutex clients map[*websocket.Conn]*client } func NewHub() *Hub { return &Hub{clients: make(map[*websocket.Conn]*client)} } func (h *Hub) Register(conn *websocket.Conn) { c := &client{conn: conn, send: make(chan []byte, 64)} h.mu.Lock() h.clients[conn] = c h.mu.Unlock() go c.writePump() } func (h *Hub) Unregister(conn *websocket.Conn) { h.mu.Lock() if c, ok := h.clients[conn]; ok { close(c.send) delete(h.clients, conn) } h.mu.Unlock() } func (h *Hub) Broadcast(msg interface{}) { data, err := json.Marshal(msg) if err != nil { log.Printf("[ws] marshal: %v", err) return } h.mu.RLock() defer h.mu.RUnlock() for _, c := range h.clients { select { case c.send <- data: default: // canal plein, client lent — on skip } } } func (h *Hub) Count() int { h.mu.RLock() defer h.mu.RUnlock() return len(h.clients) } func (c *client) writePump() { defer c.conn.Close() for data := range c.send { if err := c.conn.WriteMessage(websocket.TextMessage, data); err != nil { log.Printf("[ws] write: %v", err) return } } }