package websocketpack import ( "errors" "github.com/gorilla/websocket" ) /* * @ 作者: 秦东 @ 时间: 2025-06-12 16:19:04 @ 功能: 初始化设置 */ func InitConnection(wsConn *websocket.Conn) (conn *Connection, err error) { conn = &Connection{ WsConnect: wsConn, InChan: make(chan []byte, 1000), OutChan: make(chan []byte, 1000), CloseChan: make(chan byte, 1), } go conn.readLoop() // 启动写协程 go conn.writeLoop() return } /** @ 作者: 秦东 @ 时间: 2025-06-12 16:21:26 @ 功能: 读取消息 */ func (conn *Connection) ReadMessage() (data []byte, err error) { select { case data = <-conn.InChan: case <-conn.CloseChan: err = errors.New("connection is closeed") } return } func (conn *Connection) WriteMessage(data []byte) (err error) { select { case conn.OutChan <- data: case <-conn.CloseChan: err = errors.New("connection is closeed") } return } func (conn *Connection) Close() { // 线程安全,可多次调用 conn.WsConnect.Close() // 利用标记,让closeChan只关闭一次 conn.Mutex.Lock() if !conn.IsClosed { close(conn.CloseChan) conn.IsClosed = true } conn.Mutex.Unlock() } // 内部实现 func (conn *Connection) readLoop() { var ( data []byte err error ) for { if _, data, err = conn.WsConnect.ReadMessage(); err != nil { goto ERR } //阻塞在这里,等待inChan有空闲位置 select { case conn.InChan <- data: case <-conn.CloseChan: // closeChan 感知 conn断开 goto ERR } } ERR: conn.Close() } func (conn *Connection) writeLoop() { var ( data []byte err error ) for { select { case data = <-conn.OutChan: case <-conn.CloseChan: goto ERR } if err = conn.WsConnect.WriteMessage(websocket.TextMessage, data); err != nil { goto ERR } } ERR: conn.Close() }