Websocket: [рдкреНрд░рд╢реНрди] рдХреНрдпрд╛ рдЧреЛрд░рд┐рд▓реНрд▓рд╛ рд╡реЗрдмрд╕реИрдЯ рдиреЗ рдкреНрд░рд╕рд╛рд░рдг рд╕рдВрджреЗрд╢ рдХреЛ рдПрдХ рд╕реЗрдХрдВрдб рдореЗрдВ рд╕реАрдорд┐рдд рдХрд░ рджрд┐рдпрд╛ рд╣реИ?

рдХреЛ рдирд┐рд░реНрдорд┐рдд 26 рдЕрдХреНрддреВре░ 2020  ┬╖  8рдЯрд┐рдкреНрдкрдгрд┐рдпрд╛рдБ  ┬╖  рд╕реНрд░реЛрдд: gorilla/websocket

рдЙрд╕ рд╕рдорд╕реНрдпрд╛ рдХрд╛ рд╡рд░реНрдгрди рдХрд░реЗрдВ рдЬреЛ рдЖрдк рдХрд░ рд░рд╣реЗ рд╣реИрдВ
рдореИрдВ рдПрдХ рд╕реЗрдХрдВрдб рдореЗрдВ 100 рд╕рдВрджреЗрд╢ рдкреНрд░рд╕рд╛рд░рд┐рдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП golang.org/x/net/websocket рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддрд╛ рд╣реВрдВ рдХреЛрдИ рд╕рдорд╕реНрдпрд╛ рдирд╣реАрдВ рд╣реИ, рдЧреНрд░рд╛рд╣рдХ рдХреЛ рд╕рднреА рд╕рдВрджреЗрд╢ рдкреНрд░рд╛рдкреНрдд рд╣реЛ рд╕рдХрддреЗ рд╣реИрдВ, рд▓реЗрдХрд┐рди рдЬрдм рдореИрдВ рдЧреЛрд░рд┐рд▓реНрд▓рд╛ рд╡реЗрдмрд╕реНрдХреЗрдЯ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддрд╛ рд╣реВрдВ, рддреЛ рдХреЗрд╡рд▓ 10 рд╕реЗ рдХрдо рд╕рдВрджреЗрд╢ рдкреНрд░рд╛рдкреНрдд рд╣реЛрддрд╛ рд╣реИ, рдлрд┐рд░ webckcket clientv рднреНрд░рд╖реНрдЯ рд╣реЛ рдЬрд╛рдПрдЧрд╛ ред

тАж

рд╕рдВрд╕реНрдХрд░рдгреЛрдВ

рдЧреЛ рд╕рдВрд╕реНрдХрд░рдг: рдЧреЛ рд╕рдВрд╕реНрдХрд░рдг go1.13.11 linux / amd64

рдкреИрдХреЗрдЬ рд╕рдВрд╕реНрдХрд░рдг: c3dd95aea9779669bb3daafbd84ee0530c8ce1f1

тАж

"рдореБрдЭреЗ рдХреЛрдб рджрд┐рдЦрд╛рдУ!"
рдкреИрдХреЗрдЬ рдореБрдЦреНрдп

рдЖрдпрд╛рдд (
"рдПрдиреНрдХреЛрдбрд┐рдВрдЧ / рдЬрд╕рди"
"github.com/gorilla/websocket"
"рд▓реЙрдЧ"
"рдиреЗрдЯ / http"
"рд╕рдордп"
)

const (
// рд╕рдордп рдиреЗ рд╕рд╣рдХрд░реНрдореА рдХреЛ рдПрдХ рд╕рдВрджреЗрд╢ рд▓рд┐рдЦрдиреЗ рдХреА рдЕрдиреБрдорддрд┐ рджреАред
рд░рд╛рдЗрдЯрд╡рд╛рдЗрдЯ = 10 * рд╕рдордп

// Time allowed to read the next pong message from the peer.
pongWait = 60 * time.Second

// Send pings to peer with this period. Must be less than pongWait.
pingPeriod = (pongWait * 9) / 10

// Maximum message size allowed from peer.
maxMessageSize = 512

)

var upgrader = websocket.Upgrader {
ReadBufferSize: 1024,
WriteBufferSize: 1024,
CheckOrigin: func (r * http.Request) рдмреВрд▓ {рд╡рд╛рдкрд╕реА рд╕рдЪ},
}

var newline = [] рдмрд╛рдЗрдЯ {'\ n'}

рдЯрд╛рдЗрдк рдХреНрд▓рд╛рдЗрдВрдЯ рд╕рдВрд░рдЪрдирд╛ {
рд╣рдм * рд╣рдм
con * websocket.Conn
рдЪреИрди рд╕рдВрджреЗрд╢ рднреЗрдЬреЗрдВ
рд╕реНрдЯреНрд░рд┐рдВрдЧ рджреЗрдЦреЗрдВ
}

рдкреНрд░рдХрд╛рд░ рд╣рдм рд╕рдВрд░рдЪрдирд╛ {
рдХреНрд▓рд╛рдЗрдВрдЯ рдореИрдк [* рдХреНрд▓рд╛рдЗрдВрдЯ] рдмреВрд▓
рдЪреИрди рд╕рдВрджреЗрд╢ рдкреНрд░рд╕рд╛рд░рд┐рдд рдХрд░реЗрдВ
рд░рдЬрд┐рд╕реНрдЯрд░ рдЪрд╛рди * рдЧреНрд░рд╛рд╣рдХ
рдЕрдкрдВрдЬреАрдХреГрдд рдЪрд╛рди * рдЧреНрд░рд╛рд╣рдХ
}

func newHub () рд╣рдм {рд╡рд╛рдкрд╕реА рдФрд░ рд╣рдм {рдкреНрд░рд╕рд╛рд░рдг: рдореЗрдХ (рдЪрд╛рди рд╕рдВрджреЗрд╢),рд░рдЬрд┐рд╕реНрдЯрд░: рдореЗрдХ (рдЪрд╛рди * рдХреНрд▓рд╛рдЗрдВрдЯ),рдЕрдкрдВрдЬреАрдХреГрдд: рдмрдирд╛рдУ (рдЪрд╛рди * рдЧреНрд░рд╛рд╣рдХ),рдЧреНрд░рд╛рд╣рдХ: рдмрдирд╛рдирд╛ (рдирдХреНрд╢рд╛ [ рдЧреНрд░рд╛рд╣рдХ] рдмреВрд▓),
}

}

рдлрдВрдХ (рдПрдЪ * рд╣рдм) рд░рди () {
рдХреЗ рд▓рд┐рдпреЗ {
рдЪреБрдирддреЗ рд╣реИрдВ {
рдорд╛рдорд▓рд╛ рдЧреНрд░рд╛рд╣рдХ: = <-h.register:
h.clients [рдЧреНрд░рд╛рд╣рдХ] = рд╕рдЪ
рдорд╛рдорд▓рд╛ рдЧреНрд░рд╛рд╣рдХ: = <-h.unregister:
рдЕрдЧрд░ _, рдареАрдХ: = h.clients [рдЧреНрд░рд╛рд╣рдХ]; рдареАрдХ рд╣реИ {
рд╣рдЯрд╛рдПрдВ (рдПрдЪред рдЧреНрд░рд╛рд╣рдХ, рдЧреНрд░рд╛рд╣рдХ)
рдмрдВрдж
}
рдорд╛рдорд▓рд╛ рд╕рдВрджреЗрд╢: = <-h.broadcast:
рдЧреНрд░рд╛рд╣рдХ рдХреЗ рд▓рд┐рдП: = рд╢реНрд░реЗрдгреА h.clients {
рдЕрдЧрд░ client.see == message.LogName {
client.send <- рд╕рдВрджреЗрд╢
}
//рдЪреБрдирддреЗ рд╣реИрдВ {
// рдХреЗрд╕ client.send <- рд╕рдВрджреЗрд╢:
//рдЪреВрдХ:
// рдмрдВрдж (client.send)
// рд╣рдЯрд╛рдПрдВ (рдПрдЪред рдЧреНрд░рд╛рд╣рдХ, рдЧреНрд░рд╛рд╣рдХ)
//}
}
}
}
}

func (c * рдХреНрд▓рд╛рдЗрдВрдЯ) readPump () {
рдбреЗрдлрд╝ рдлрдВрдХ () {
c.hub.unregister <- рд╕реА
_ = c.conn.Close ()
} ()
c.conn.SetReadLimit (maxMessageSize)
_ = c.conn.SetReadDeadline (time.Now ()ред Add (pongWait)
c.conn.SetPongHandler (func (string) error {_ = c.conn.SetReadDeadline (time.Now ()ред add (pongWait)); рд╡рд╛рдкрд╕ nil})
рдХреЗ рд▓рд┐рдпреЗ {
_, рд╕рдВрджреЗрд╢, рдЧрд▓рдд: = c.conn.ReadMessage ()
рдЕрдЧрд░ рдЧрд▓рдд рд╣реИ! = nil {
рдЕрдЧрд░ websocketред
ErrorLogger.Printf ("readPump рддреНрд░реБрдЯрд┐ рдХреЗ рд╕рд╛рде рд╡рд┐рдлрд▓:% v", рдЗрд░)
}
рдЯреВрдЯрдирд╛
}

    type recv struct {
        LogName string `json:"logName"`
    }
    var rcv = &recv{}
    if err := json.Unmarshal(message, &rcv); err != nil {
        c.hub.unregister <- c
        ErrorLogger.Printf("%s",err)
        break
    }
    c.see = rcv.LogName
}

}

func (c * рдХреНрд▓рд╛рдЗрдВрдЯ) рд░рд╛рдЗрдЯрдкрдВрдк () {
рдЯрд┐рдХрд░: = рд╕рдордп
рдбреЗрдлрд╝ рдлрдВрдХ () {
рдЯрд┐рдХрд░ .рдЯреЙрдк ()
_ = c.conn.Close ()
} ()
рдХреЗ рд▓рд┐рдпреЗ {
рдЪреБрдирддреЗ рд╣реИрдВ {
рдорд╛рдорд▓рд╛ рд╕рдВрджреЗрд╢, рдареАрдХ рд╣реИ: = <-send:
_ = c.conn.SetWriteDeadline (time.Now ()ред Add (writeWait)
рдЕрдЧрд░! рдареАрдХ рд╣реИ {
// рд╣рдм рдиреЗ рдЪреИрдирд▓ рдмрдВрдж рдХрд░ рджрд┐рдпрд╛ред
_ = c.conn.WriteMessage (websocket.CloseMessage, [] рдмрд╛рдЗрдЯ {})
рд╡рд╛рдкрд╕реА
}

        w, err := c.conn.NextWriter(websocket.TextMessage)
        if err != nil {
            return
        }
        msgByte, _ := json.Marshal(message)
        _, _ = w.Write(msgByte)

        // Add queued chat messages to the current websocket message.
        n := len(c.send)
        _, _ = w.Write(newline)
        for i := 0; i < n; i++ {
            for msg := range c.send {
                msgByte, _ := json.Marshal(msg)
                _, err := w.Write(msgByte)
                if err != nil {
                    newHub().unregister <- c
                    ErrorLogger.Printf("%s", err)
                    break
                }
            }
        }
        if err := w.Close(); err != nil {
            return
        }
    case <-ticker.C:
        _ = c.conn.SetWriteDeadline(time.Now().Add(writeWait))
        if err := c.conn.WriteMessage(websocket.PingMessage, nil); err != nil {
            return
        }
    }
}

}

// serveWs рд╕рд╣рдХрд░реНрдореА рд╕реЗ websocket рдЕрдиреБрд░реЛрдз рд╕рдВрднрд╛рд▓рддрд╛ рд╣реИред
рдлрдВрдХ рд╕рд░реНрд╡реНрд╕ (рд╣рдм * рд╣рдм, рдбрдмреНрд▓реНрдпреВ http.esponseWriter, рдЖрд░ * http.Request) {
рдХреЙрди, рдЗрд░реЗрдЯ: = upgrader.Upgrad (w, r, nil)
рдЕрдЧрд░ рдЧрд▓рдд рд╣реИ! = nil {
log.Fatal (рдЗрд░реЗрдЯ)
рд╡рд╛рдкрд╕реА
}
рдЧреНрд░рд╛рд╣рдХ: = & рдЧреНрд░рд╛рд╣рдХ {рд╣рдм: рд╣рдм, рдХреЙрди: рдХреЙрди, рднреЗрдЬреЗрдВ: рдореЗрдХ (рдЪрд╛рди рд╕рдВрджреЗрд╢, 1)}
client.hub.register <- рдХреНрд▓рд╛рдЗрдВрдЯ

// Allow collection of memory referenced by the caller by doing all work in
// new goroutines.
go client.writePump()
go client.readPump()

}

рд╕рдмрд╕реЗ рдЙрдкрдпреЛрдЧреА рдЯрд┐рдкреНрдкрдгреА

рдЧреЛрд░рд┐рд▓реНрд▓рд╛ рдХреЗ рдкрд╛рд╕ рдПрдХ рдЪрд░ рдпрд╛ рдПрдкреАрдЖрдИ рдирд╣реАрдВ рд╣реИ рдЬреЛ рдкреНрд░рддрд┐ рд╕реЗрдХрдВрдб рд╕рдВрджреЗрд╢реЛрдВ рдХреА рд╕рдВрдЦреНрдпрд╛ рдХреЛ рд╕реАрдорд┐рдд рдХрд░рддрд╛ рд╣реИред

рдПрдХ рдПрдХрд▓ рд╡реЗрдмрд╕рд░реНрдХреЗрдЯ рд╕рдВрджреЗрд╢ рдореЗрдВ рдХрдИ JSON рджрд╕реНрддрд╛рд╡реЗрдЬрд╝реЛрдВ рдХреЛ рдкреИрдХ рдХрд░рдиреЗ рдХрд╛ рдХреЛрдб рддрдм рдЯреНрд░рд┐рдЧрд░ рд╣реЛрдЧрд╛ рдЬрдм рд╕рдВрджреЗрд╢ рдмрд╣реБрдд рдЙрдЪреНрдЪ рджрд░ рдкрд░ рднреЗрдЬрд╛ рдЬрд╛рдПрдЧрд╛ред рдпрд╣ рджреЗрдЦрддреЗ рд╣реБрдП рдХрд┐ рдЖрдкрдХреЗ рдЧреНрд░рд╛рд╣рдХ рдХреЛ рдПрдХ рд╣реА WebSocket рд╕рдВрджреЗрд╢ рдореЗрдВ рдХрдИ JSON рджрд╕реНрддрд╛рд╡реЗрдЬрд╝реЛрдВ рдХреЛ рд╕рдВрднрд╛рд▓рдиреЗ рдХреЗ рд▓рд┐рдП рдбрд┐рдЬрд╝рд╛рдЗрди рдирд╣реАрдВ рдХрд┐рдпрд╛ рдЧрдпрд╛ рд╣реИ, рдЖрдк рдмрд╣реБрдд рдЕрдзрд┐рдХ рджрд░ рдкрд░ рд╕рдВрджреЗрд╢ рднреЗрдЬрддреЗ рд╕рдордп рдЕрдкрдиреЗ рдЖрд╡реЗрджрди рдХреЛ рд╕рдВрджреЗрд╢ рдЦреЛрдиреЗ рдХреА рдЙрдореНрдореАрдж рдХрд░ рд╕рдХрддреЗ рд╣реИрдВред

рд╣рдЯрд╛рдП рдЧрдП рдХреЛрдб рдХреЛ рд╡рд╛рдкрд╕ рдЯрд┐рдкреНрдкрдгреА рдФрд░ рдкрд░реАрдХреНрд╖рдг рдХреЗ рдПрдХ рдЬреЛрдбрд╝реЗ рдХреЛ рдЙрджреНрдзреГрдд рдХрд░реЗрдВред

рд╕рднреА 8 рдЯрд┐рдкреНрдкрдгрд┐рдпрд╛рдБ

рдХреНрдпрд╛ рдЖрдкрдХреЗ рдЧреНрд░рд╛рд╣рдХ рдХреЛ рдПрдХ рд╣реА рд╡реЗрдмрд╕реНрдХреЗрдЯ рд╕рдВрджреЗрд╢ рдореЗрдВ рдХрдИ JSON рджрд╕реНрддрд╛рд╡реЗрдЬрд╝реЛрдВ рдХреЛ рд╕рдВрднрд╛рд▓рдиреЗ рдХреЗ рд▓рд┐рдП рд▓рд┐рдЦрд╛ рдЧрдпрд╛ рд╣реИ?

рдПрдХреНрд╕ / рдиреЗрдЯ / рд╡реЗрдмрд╕реЛрдХреЗрдЯ рдХреЗ рд╕рд╛рде рдХреЛрдб рджрд┐рдЦрд╛рдПрдВ рдЬреЛ рдХрд╛рдо рдХрд░рддрд╛ рд╣реИред

рдХреНрдпрд╛ рдЖрдкрдХреЗ рдЧреНрд░рд╛рд╣рдХ рдХреЛ рдПрдХ рд╣реА рд╡реЗрдмрд╕реНрдХреЗрдЯ рд╕рдВрджреЗрд╢ рдореЗрдВ рдХрдИ JSON рджрд╕реНрддрд╛рд╡реЗрдЬрд╝реЛрдВ рдХреЛ рд╕рдВрднрд╛рд▓рдиреЗ рдХреЗ рд▓рд┐рдП рд▓рд┐рдЦрд╛ рдЧрдпрд╛ рд╣реИ?

рдПрдХреНрд╕ / рдиреЗрдЯ / рд╡реЗрдмрд╕реЛрдХреЗрдЯ рдХреЗ рд╕рд╛рде рдХреЛрдб рджрд┐рдЦрд╛рдПрдВ рдЬреЛ рдХрд╛рдо рдХрд░рддрд╛ рд╣реИред

рдирд╣реАрдВ рди

`` `рдкреИрдХреЗрдЬ рдореБрдЦреНрдп

рдЖрдпрд╛рдд (
"рдПрдиреНрдХреЛрдбрд┐рдВрдЧ / рдЬрд╕рди"
"golang.org/x/net/websocket"
"рдЖрдИрдУ"
)

// рд╡реЗрдмрд╕реЛрдХреЗрдЯ ховцИ╖ ховцИ╖
рдЯрд╛рдЗрдк рдХреНрд▓рд╛рдЗрдВрдЯ рд╕рдВрд░рдЪрдирд╛ {
рдЖрдИрдбреА рд╕реНрдЯреНрд░рд┐рдВрдЧ
рд╕реЙрдХреЗрдЯ * websocket.Conn
рдЪреИрди рд╕рдВрджреЗрд╢ рднреЗрдЬреЗрдВ
рд╕реНрдЯреНрд░рд┐рдВрдЧ рджреЗрдЦреЗрдВ
}

// члп ховцИ╖ члп
рдкреНрд░рдХрд╛рд░
рдХреНрд▓рд╛рдЗрдВрдЯ рдореИрдк [* рдХреНрд▓рд╛рдЗрдВрдЯ] рдмреВрд▓
рдЪреИрди рд╕рдВрджреЗрд╢ рдкреНрд░рд╕рд╛рд░рд┐рдд рдХрд░реЗрдВ
рд░рдЬрд┐рд╕реНрдЯрд░ рдЪрд╛рди * рдЧреНрд░рд╛рд╣рдХ
рдЕрдкрдВрдЬреАрдХреГрдд рдЪрд╛рди * рдЧреНрд░рд╛рд╣рдХ
}

var рдкреНрд░рдмрдВрдзрдХ = рдЧреНрд░рд╛рд╣рдХ рдкреНрд░рдмрдВрдзрдХ {
рдкреНрд░рд╕рд╛рд░рдг: рдореЗрдХ (рдЪрд╛рди рд╕рдВрджреЗрд╢),
рд░рдЬрд┐рд╕реНрдЯрд░: рдореЗрдХ (рдЪрд╛рди рдХреНрд▓рд╛рдЗрдВрдЯ),рдЕрдкрдВрдЬреАрдХреГрдд: рдмрдирд╛рдУ (рдЪрд╛рди * рдЧреНрд░рд╛рд╣рдХ),рдЧреНрд░рд╛рд╣рдХ: рдмрдирд╛рдирд╛ (рдирдХреНрд╢рд╛ [ рдЧреНрд░рд╛рд╣рдХ] рдмреВрд▓),
}

func (рдкреНрд░рдмрдВрдзрдХ * clientManager) рдкреНрд░рд╛рд░рдВрдн () {
рдбреЗрдлрд╝ рдлрдВрдХ () {
рдЕрдЧрд░ рдЧрд▓рдд рд╣реИ: = рдкреБрдирд░реНрдкреНрд░рд╛рдкреНрдд (); рдЧрд╝рд▓рддреА рд╕реЗ! = nil {
ErrorLogger.Printf ("рдкреНрд░рдмрдВрдзрдХ рдкреНрд░рд╛рд░рдВрдн () рдШрдмрд░рд╛рд╣рдЯ")
}
} ()

for {
    select {
    case conn := <-manager.register:
        manager.clients[conn] = true
    case conn := <-manager.unregister:
        if _, ok := manager.clients[conn]; ok {
            close(conn.send)
            _ = conn.socket.Close()
            delete(manager.clients, conn)
        }
    case msg := <-manager.broadcast:
        for conn := range manager.clients {
            if conn.see == msg.LogName {
                conn.send <- msg
            }
        }
    }
}

}

func (c * client) рд▓рд┐рдЦрдирд╛ () {

for msg := range c.send {
    msgByte, _ := json.Marshal(msg) // х┐╜чХещФЩшпп
    _, err := c.socket.Write(msgByte)
    if err != nil {
        manager.unregister <- c
        ErrorLogger.Printf("%s",err)
        break
    }
}

}

func (c * рдХреНрд▓рд╛рдЗрдВрдЯ) рдкрдврд╝рд╛ () {
рдХреЗ рд▓рд┐рдпреЗ {
var рдЙрддреНрддрд░ рд╕реНрдЯреНрд░рд┐рдВрдЧ
рдЕрдЧрд░ рдЧрд▓рдд рд╣реИ: = websocket.Message.Receive (c.socket, & reply); рдЧрд╝рд▓рддреА рд╕реЗ! = nil {
рдЕрдЧрд░ рдЧрд▓рдд рд╣реИ! = io.EOF {
ErrorLogger.Printf ("% s", рдЗрд░реЗрдЯ)
manager.unregister <- рд╕реА
}
рдЯреВрдЯрдирд╛
}
рдЯрд╛рдЗрдк рдЖрд░рдИрд╡реА рд╕реНрдЯреНрд░рдХреНрдЪрд░ {
LogName рд╕реНрдЯреНрд░рд┐рдВрдЧ json:"logName"
}
var rcv = & recv {}
рдЕрдЧрд░ рдЧрд▓рдд рд╣реИ: = json.Unmarshal ([] рдмрд╛рдЗрдЯ (рдЙрддреНрддрд░), рдФрд░ рдЖрд░рд╕реАрд╡реА); рдЧрд╝рд▓рддреА рд╕реЗ! = nil {
manager.unregister <- рд╕реА
ErrorLogger.Printf ("% s", рдЗрд░реЗрдЯ)
рдЯреВрдЯрдирд╛
}
c.see = rcv.LogName
}
}
`` `

рдЧреЛрд░рд┐рд▓реНрд▓рд╛ рдкреИрдХреЗрдЬ рдореЗрдВ рдПрдХ рд╕реЗрдХрдВрдб рдореЗрдВ рдкреНрд░рд╕рд╛рд░рдг рд╕рдВрджреЗрд╢ рдХреА рд╕реАрдорд╛ рдирд╣реАрдВ рд╣реИред

рдпрджрд┐ рдЖрдкрдХрд╛ рдХреНрд▓рд╛рдЗрдВрдЯ рдХрд┐рд╕реА WebSocket рдореИрд╕реЗрдЬ рдореЗрдВ рдХрдИ JSON рдбреЙрдХреНрдпреВрдореЗрдВрдЯреНрд╕ рдХреЛ рд╣реИрдВрдбрд▓ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдирд╣реАрдВ рд▓рд┐рдЦрд╛ рдЧрдпрд╛ рд╣реИ, рддреЛ рдЕрдкрдиреЗ рдХреЛрдб рдХреЛ рд╣рдЯрд╛ рджреЗрдВ рдЬреЛ рдПрдХ рдореИрд╕реЗрдЬ рдореЗрдВ рдХрдИ рдбреЙрдХреНрдпреВрдореЗрдВрдЯреНрд╕ рд▓рд┐рдЦрддрд╛ рд╣реИред

рдЖрдкрдХрд╛ x / net / websocket рдХреЛрдб рдПрдХ JSON рджрд╕реНрддрд╛рд╡реЗрдЬрд╝ рдкреНрд░рддрд┐ WebSocket рд╕рдВрджреЗрд╢ рд▓рд┐рдЦрддрд╛ рд╣реИред рдпрджрд┐ рдЖрдк рдЧреЛрд░рд┐рд▓реНрд▓рд╛ рдХреЛрдб рдХреЗ рд╕рд╛рде рдРрд╕рд╛ рд╣реА рдХрд░рддреЗ рд╣реИрдВ, рддреЛ рдЖрд╡реЗрджрди рд╕рдВрднрд╡рддрдГ рдЙрдореНрдореАрдж рдХреЗ рдореБрддрд╛рдмрд┐рдХ рдХрд╛рдо рдХрд░реЗрдЧрд╛ред

рдПрдХ рд╕рдВрджреЗрд╢ рдореЗрдВ рдХрдИ рджрд╕реНрддрд╛рд╡реЗрдЬрд╝ рд▓рд┐рдЦрдиреЗ рд╡рд╛рд▓реЗ рдЕрдкрдиреЗ рдХреЛрдб рдХреЛ рд╣рдЯрд╛ рджреЗрдВред

рдХреНрдпрд╛ рдЖрдкрдХрд╛ рдпрд╣ рдорддрд▓рдм рдерд╛?

            // Add queued chat messages to the current websocket message.
            n := len(c.send)
            _, _ = w.Write(newline)
            for i := 0; i < n; i++ {
                for msg := range c.send {
                    msgByte, _ := json.Marshal(msg)
                    _, err := w.Write(msgByte)
                    if err != nil {
                        newHub().unregister <- c
                        ErrorLogger.Printf("%s", err)
                        break
                    }
                }
            }

рд╣рд╛рдВ, рдпрд╣ рдЖрдкрдХрд╛ рдХреЛрдб рд╣реИ рдЬреЛ рдПрдХ рд╡реЗрдмрд╕реИрдЯ рд╕рдВрджреЗрд╢ рдореЗрдВ рдХрдИ рджрд╕реНрддрд╛рд╡реЗрдЬрд╝ рдЬреЛрдбрд╝рддрд╛ рд╣реИред

рдареАрдХ рд╣реИ, рдХреНрдпрд╛ рдЧреЛрд░рд┐рд▓реНрд▓рд╛ рдХреЗ рдкрд╛рд╕ рдХреЛрдИ рдЪрд░ рдпрд╛ рдПрдкреАрдЖрдИ рд╣реИ рдЬреЛ рдЧреНрд░рд╛рд╣рдХ рдХреЛ рджреВрд╕рд░реЗ рд╕рдВрджреЗрд╢ рдореЗрдВ рдЕрдзрд┐рдХ рд╕рдВрджреЗрд╢ рдкреНрд░рд╛рдкреНрдд рдХрд░ рд╕рдХрддрд╛ рд╣реИ illa

рдЧреЛрд░рд┐рд▓реНрд▓рд╛ рдХреЗ рдкрд╛рд╕ рдПрдХ рдЪрд░ рдпрд╛ рдПрдкреАрдЖрдИ рдирд╣реАрдВ рд╣реИ рдЬреЛ рдкреНрд░рддрд┐ рд╕реЗрдХрдВрдб рд╕рдВрджреЗрд╢реЛрдВ рдХреА рд╕рдВрдЦреНрдпрд╛ рдХреЛ рд╕реАрдорд┐рдд рдХрд░рддрд╛ рд╣реИред

рдПрдХ рдПрдХрд▓ рд╡реЗрдмрд╕рд░реНрдХреЗрдЯ рд╕рдВрджреЗрд╢ рдореЗрдВ рдХрдИ JSON рджрд╕реНрддрд╛рд╡реЗрдЬрд╝реЛрдВ рдХреЛ рдкреИрдХ рдХрд░рдиреЗ рдХрд╛ рдХреЛрдб рддрдм рдЯреНрд░рд┐рдЧрд░ рд╣реЛрдЧрд╛ рдЬрдм рд╕рдВрджреЗрд╢ рдмрд╣реБрдд рдЙрдЪреНрдЪ рджрд░ рдкрд░ рднреЗрдЬрд╛ рдЬрд╛рдПрдЧрд╛ред рдпрд╣ рджреЗрдЦрддреЗ рд╣реБрдП рдХрд┐ рдЖрдкрдХреЗ рдЧреНрд░рд╛рд╣рдХ рдХреЛ рдПрдХ рд╣реА WebSocket рд╕рдВрджреЗрд╢ рдореЗрдВ рдХрдИ JSON рджрд╕реНрддрд╛рд╡реЗрдЬрд╝реЛрдВ рдХреЛ рд╕рдВрднрд╛рд▓рдиреЗ рдХреЗ рд▓рд┐рдП рдбрд┐рдЬрд╝рд╛рдЗрди рдирд╣реАрдВ рдХрд┐рдпрд╛ рдЧрдпрд╛ рд╣реИ, рдЖрдк рдмрд╣реБрдд рдЕрдзрд┐рдХ рджрд░ рдкрд░ рд╕рдВрджреЗрд╢ рднреЗрдЬрддреЗ рд╕рдордп рдЕрдкрдиреЗ рдЖрд╡реЗрджрди рдХреЛ рд╕рдВрджреЗрд╢ рдЦреЛрдиреЗ рдХреА рдЙрдореНрдореАрдж рдХрд░ рд╕рдХрддреЗ рд╣реИрдВред

рд╣рдЯрд╛рдП рдЧрдП рдХреЛрдб рдХреЛ рд╡рд╛рдкрд╕ рдЯрд┐рдкреНрдкрдгреА рдФрд░ рдкрд░реАрдХреНрд╖рдг рдХреЗ рдПрдХ рдЬреЛрдбрд╝реЗ рдХреЛ рдЙрджреНрдзреГрдд рдХрд░реЗрдВред

рдХреНрдпрд╛ рдпрд╣ рдкреГрд╖реНрда рдЙрдкрдпреЛрдЧреА рдерд╛?
0 / 5 - 0 рд░реЗрдЯрд┐рдВрдЧреНрд╕

рд╕рдВрдмрдВрдзрд┐рдд рдореБрджреНрджреЛрдВ

bcashier picture bcashier  ┬╖  8рдЯрд┐рдкреНрдкрдгрд┐рдпрд╛рдБ

Mjavala picture Mjavala  ┬╖  5рдЯрд┐рдкреНрдкрдгрд┐рдпрд╛рдБ

deanm picture deanm  ┬╖  15рдЯрд┐рдкреНрдкрдгрд┐рдпрд╛рдБ

fbens picture fbens  ┬╖  3рдЯрд┐рдкреНрдкрдгрд┐рдпрд╛рдБ

markusthoemmes picture markusthoemmes  ┬╖  7рдЯрд┐рдкреНрдкрдгрд┐рдпрд╛рдБ