WebSocket библиотека Go (Golang): gorilla/websocket и стандартный net/http
WebSocket — это протокол, обеспечивающий полнодуплексную связь между клиентом и сервером поверх одного долгоживущего TCP-соединения. В отличие от классического HTTP, после установки соединения данные могут передаваться в обе стороны в любой момент, без постоянных запросов от клиента. Это идеальное решение для чатов, уведомлений в реальном времени, онлайн-игр и трейдинговых платформ.
В экосистеме Go (Golang) существует несколько способов работы с WebSocket. Самой популярной и проверенной временем является библиотека gorilla/websocket. Однако, начиная с Go 1.22, появилась возможность реализовать базовый WebSocket-сервер без сторонних зависимостей, используя стандартный пакет net/http. В этой статье мы подробно разберём оба подхода.
Установка библиотеки gorilla/websocket
Для начала работы с gorilla/websocket установите её через go get:
go get github.com/gorilla/websocket
Библиотека предоставляет удобный API для создания как серверной, так и клиентской части. Она обрабатывает рукопожатие (handshake), фрейминг сообщений, поддерживает сжатие и автоматический пинг/понг.
Сервер WebSocket на gorilla/websocket
Рассмотрим пример простого эхо-сервера. Клиент отправляет сообщение, сервер возвращает его обратно:
package main
import (
"log"
"net/http"
"github.com/gorilla/websocket"
)
var upgrader = websocket.Upgrader{
CheckOrigin: func(r *http.Request) bool {
return true // разрешаем любые источники (для разработки)
},
}
func echoHandler(w http.ResponseWriter, r *http.Request) {
conn, err := upgrader.Upgrade(w, r, nil)
if err != nil {
log.Print("Upgrade failed:", err)
return
}
defer conn.Close()
for {
messageType, message, err := conn.ReadMessage()
if err != nil {
log.Println("Read error:", err)
break
}
log.Printf("Received: %s", message)
if err := conn.WriteMessage(messageType, message); err != nil {
log.Println("Write error:", err)
break
}
}
}
func main() {
http.HandleFunc("/echo", echoHandler)
log.Fatal(http.ListenAndServe(":8080", nil))
}
Здесь Upgrader преобразует обычный HTTP-запрос в WebSocket-соединение. Функция CheckOrigin контролирует, с каких доменов разрешены подключения. В production рекомендуется проверять конкретные источники.
Клиент WebSocket на gorilla/websocket
Пример клиента, который подключается к нашему серверу и отправляет сообщение:
package main
import (
"log"
"os"
"os/signal"
"time"
"github.com/gorilla/websocket"
)
func main() {
interrupt := make(chan os.Signal, 1)
signal.Notify(interrupt, os.Interrupt)
url := "ws://localhost:8080/echo"
c, _, err := websocket.DefaultDialer.Dial(url, nil)
if err != nil {
log.Fatal("dial:", err)
}
defer c.Close()
done := make(chan struct{})
// Горутина для чтения ответов
go func() {
defer close(done)
for {
_, message, err := c.ReadMessage()
if err != nil {
log.Println("read:", err)
return
}
log.Printf("recv: %s", message)
}
}()
// Отправка сообщения
ticker := time.NewTicker(time.Second)
defer ticker.Stop()
for {
select {
case <-done:
return
case t := <-ticker.C:
err := c.WriteMessage(websocket.TextMessage, []byte(t.String()))
if err != nil {
log.Println("write:", err)
return
}
case <-interrupt:
log.Println("interrupt")
// Чистое закрытие соединения
err := c.WriteMessage(websocket.CloseMessage, websocket.FormatCloseMessage(websocket.CloseNormalClosure, ""))
if err != nil {
log.Println("write close:", err)
return
}
select {
case <-done:
case <-time.After(time.Second):
}
return
}
}
}
Стандартный net/http (Go 1.22+)
Начиная с Go 1.22, пакет net/http содержит встроенную поддержку WebSocket. Это удобно, когда не хочется добавлять внешние зависимости. Пример сервера:
package main
import (
"io"
"log"
"net/http"
)
func wsHandler(w http.ResponseWriter, r *http.Request) {
// Проверяем, что это WebSocket-запрос
if r.Header.Get("Upgrade") != "websocket" {
http.Error(w, "Not a websocket request", 400)
return
}
// Получаем соединение
conn, err := http.Upgrade(w, r, nil)
if err != nil {
log.Println("Upgrade error:", err) Также в библиотеке
Мониторинг приложений C# (.NET) с помощью AppMetrics
Работа с XML в Java: DOM, SAX, StAX и JAXB
Парсинг HTML в C++: библиотеки и примеры для работы с DOM и XPath
Сериализация объектов в Swift (iOS/macOS): Codable, JSON и PropertyList
Elasticsearch клиент для Rust: официальная библиотека elasticsearch-rs