In the chat example there is a file called hub.go.
https://github.com/gorilla/websocket/blob/master/examples/chat/hub.go
I have made some changes to that file and it looks like this:
type hub struct {
// Registered connections.
connections map[int64]*connection
sync.RWMutex
// Inbound messages from the connections.
broadcast chan []byte
// Register requests from the connections.
register chan *connection
// Unregister requests from connections.
unregister chan *connection
}
var wsHub = hub{
connections: make(map[int64]*connection),
broadcast: make(chan []byte),
register: make(chan *connection),
unregister: make(chan *connection),
}
func (h *hub) init() {
for {
select {
case c := <-h.register:
h.Lock()
h.connections[c.userId] = c
h.Unlock()
case c := <-h.unregister:
h.RLock()
_, ok := h.connections[c.userId]
h.RUnlock()
if ok {
h.Lock()
delete(h.connections, c.userId)
h.Unlock()
close(c.send)
}
case m := <-h.broadcast:
for _, c := range h.connections {
select {
case c.send <- m:
default:
close(c.send)
delete(h.connections, c.userId)
}
}
}
}
}
I have added sync.RWMutex to the hub struct but I am not sure if this is necessary. Why is it not included in the example? Maybe I am missing something? Is it overkill to lock and unlock?
And also the last case in the init() method I'm not sure how to lock and unlock because it reads and writes at the same time. Should I use both the Rlock() and Lock()? How would that look like?