用golang写一个简易聊天室

这里websocket库用的是github.com/lxzan/gws. 实现上非常的简介, 没有任何依赖; 事件驱动; 支持中间件; 每个连接自带消息队列, 不会被单条消息的处理阻塞通信.

  • 核心接口如下, 是不是熟悉的味道

    type EventHandler interface {
      OnRecover(socket *Conn, exception interface{})
      OnOpen(socket *Conn)
      OnClose(socket *Conn, code Code, reason []byte)
      OnMessage(socket *Conn, m *Message)
      OnError(socket *Conn, err error)
      OnPing(socket *Conn, m []byte)
      OnPong(socket *Conn, m []byte)
    }
  • 聊天室代码

    package main
    
    import (
      "encoding/json"
      "github.com/lxzan/gws"
      "net/http"
      "sync"
    )
    
    var handler = &Handler{sessions: sync.Map{}}
    
    type Handler struct {
      sessions sync.Map
    }
    
    func (h *Handler) OnRecover(socket *gws.Conn, exception interface{}) {}
    
    // 把连接保存到sync.Map, 用于websocket连接之间的通信
    func (h *Handler) OnOpen(socket *gws.Conn) {
      name, _ := socket.Storage.Get("name")
      h.sessions.Store(name.(string), socket)
    }
    
    func (h *Handler) OnClose(socket *gws.Conn, code gws.Code, reason []byte) {}
    
    // 通信格式
    type Request struct {
      To      string `json:"to"`
      Message string `json:"message"`
    }
    
    func (h *Handler) OnMessage(socket *gws.Conn, m *gws.Message) {
      var request Request
      json.Unmarshal(m.Bytes(), &request)
    
      me, _ := socket.Storage.Get("name")
      if me.(string) == request.To {
          socket.Write(m.MessageType(), m.Bytes())
          m.Close()
      } else {
          if receiver, ok := h.sessions.Load(request.To); ok {
              h.OnMessage(receiver.(*gws.Conn), m)
          }
      }
    }
    
    func (h *Handler) OnError(socket *gws.Conn, err error) {}
    
    func (h *Handler) OnPing(socket *gws.Conn, m []byte) {}
    
    func (h *Handler) OnPong(socket *gws.Conn, m []byte) {}
    
    func main() {
      var upgrader = gws.Upgrader{
          ServerOptions: &gws.ServerOptions{
              LogEnabled:      true,
              CompressEnabled: false,
          },
          
          // 用户名由url带进来, 存到storage里面
          CheckOrigin: func(r *gws.Request) bool {
              r.Storage.Put("name", r.URL.Query().Get("name"))
              return true
          },
      }
    
      http.HandleFunc("/ws", func(w http.ResponseWriter, r *http.Request) {
          upgrader.Upgrade(w, r, handler)
      })
    
      http.ListenAndServe(":3000", nil)
    }

你可能感兴趣的:(websocket聊天室go)