Грубо говоря, вот так можно
package main
import (
"log"
"net/http"
"sync/atomic"
"time"
"github.com/gorilla/websocket"
"github.com/julienschmidt/httprouter"
)
type Client struct {
c *websocket.Conn
}
func (this *Client) sendMessage(msg string) {
err := this.c.WriteMessage(websocket.TextMessage, []byte(msg))
if err != nil {
log.Println("write:", err)
}
}
type Pool struct {
lastId uint64
addChan chan (*Client)
removeChan chan (uint64)
msgChan chan (string)
clients map[uint64]*Client
}
func (this *Pool) serviceRoutine() {
for {
select {
case newClient := <-this.addChan:
this.clients[this.lastId] = newClient
case id := <-this.removeChan:
delete(this.clients, id)
log.Printf("Client with id %d disconnected\n", id)
case msg := <-this.msgChan:
for _, client := range this.clients {
client.sendMessage(msg)
}
}
}
}
func (this *Pool) addClient(client *Client) uint64 {
newId := atomic.AddUint64(&this.lastId, 1)
this.addChan <- client
log.Printf("Client with id %d connected\n", newId)
return newId
}
func NewPool() *Pool {
pool := &Pool{
addChan: make(chan *Client),
removeChan: make(chan uint64),
msgChan: make(chan string, 5),
clients: make(map[uint64]*Client),
}
go pool.serviceRoutine()
return pool
}
var pool *Pool = NewPool()
func main() {
go func() {
//здесь я получаю данные которые необходимо "проксировать"
ticker := time.NewTicker(time.Second)
for range ticker.C {
// Просто посылаем текущее время раз в секунду всем подключенным клиентам
pool.msgChan <- time.Now().Format("Mon Jan 2 15:04:05 -0700 MST 2006")
}
}()
router := httprouter.New()
router.GET("/events/ws/", EventsWSHandler)
router.NotFound = http.FileServer(http.Dir("www/"))
log.Fatal(http.ListenAndServe(":3000", router))
}
var upgrader = websocket.Upgrader{}
func EventsWSHandler(w http.ResponseWriter, r *http.Request, _ httprouter.Params) {
c, err := upgrader.Upgrade(w, r, nil)
if err != nil {
log.Print("upgrade:", err)
return
}
defer c.Close()
id := pool.addClient(&Client{c: c})
defer func() {
pool.removeChan <- id
}()
for {
mt, message, err := c.ReadMessage()
if err != nil {
log.Println("read:", err)
break
}
log.Printf("recv: %d %s", mt, message)
}
}