package main import ( "fmt" "strings" "time" "github.com/gorilla/websocket" ) var usernames = make(map[*websocket.Conn]string) var nameToConn = make(map[string]*websocket.Conn) func handleIncomingMessage(sender *websocket.Conn, msg string) { if _, ok := usernames[sender]; !ok { username := strings.TrimSpace(msg) if username == "" || username == "server" { sender.WriteJSON(newError("You have an illegal username.")) return } if _, ok = nameToConn[username]; ok { sender.WriteJSON(newError("The specified username is already taken.")) return } sendUserList(sender) usernames[sender] = username nameToConn[username] = sender m := newMessage(msgJoin, "server", username) m.dispatch() return } sendChatMessage(sender, msg) } func handleDisconnection(sender *websocket.Conn) { username, ok := usernames[sender] if !ok { fmt.Println("leave without registering") return } m := newMessage(msgLeave, "server", username) m.dispatch() delete(usernames, sender) delete(nameToConn, username) } type messageType string const ( msgChat messageType = "message" msgJoin messageType = "join" msgLeave messageType = "leave" msgErr messageType = "error" msgUserList messageType = "users" ) type message struct { Type messageType `json:"type"` Sender string `json:"sender"` Content interface{} `json:"content"` Date time.Time `json:"date"` Success bool `json:"success"` } func newError(content string) message { return message{ Type: msgErr, Sender: "", Content: content, Date: time.Now().UTC(), Success: false, } } func newMessage(msgType messageType, sender string, content string) message { return message{ Type: msgType, Sender: sender, Content: content, Date: time.Now().UTC(), Success: true, } } func (m message) dispatch() { for client := range usernames { _ = client.WriteJSON(m) } } func sendUserList(who *websocket.Conn) { list := []string{} for _, username := range usernames { list = append(list, username) } m := message{ Type: msgUserList, Sender: "", Content: list, Date: time.Now().UTC(), Success: true, } _ = who.WriteJSON(m) } func sendChatMessage(sender *websocket.Conn, msg string) { m := newMessage(msgChat, usernames[sender], msg) m.dispatch() }