WebSocket на Go: создание real-time приложений
Современные веб-приложения все чаще требуют мгновенной передачи данных между клиентом и сервером. Традиционные HTTP-запросы с их циклом «запрос-ответ» не подходят для задач, где важна скорость: онлайн-чаты, биржевые котировки, многопользовательские игры или уведомления в реальном времени. Здесь на помощь приходит WebSocket — протокол, обеспечивающий постоянное двустороннее соединение. В этой статье мы разберем, как реализовать WebSocket на Go (Golang), от базового сервера до полноценного real-time приложения.
Что такое WebSocket и почему Go?
WebSocket — это протокол поверх TCP, который позволяет установить постоянное соединение между клиентом (браузером) и сервером. После рукопожатия (handshake) данные передаются в обоих направлениях без дополнительных HTTP-заголовков, что значительно снижает задержки.
Почему Go? Язык Go идеально подходит для WebSocket-серверов благодаря встроенной поддержке конкурентности (горутины и каналы), высокой производительности и простоте написания сетевого кода. В отличие от Node.js, Go не требует внешних циклов событий, а его компилируемая природа дает преимущество в скорости.
Базовый WebSocket сервер на Go
Для работы с WebSocket в Go мы будем использовать популярную библиотеку gorilla/websocket. Она предоставляет удобный API и обрабатывает детали протокола.
Установите библиотеку:
go get github.com/gorilla/websocketТеперь напишем простой эхо-сервер, который отправляет обратно все, что получает от клиента.
package main
import ( "log" "net/http" "github.com/gorilla/websocket")
var upgrader = websocket.Upgrader{ CheckOrigin: func(r *http.Request) bool { return true // Для разработки. В продакшене проверяйте Origin. },}
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("Получено: %s", message)
if err := conn.WriteMessage(messageType, message); err != nil { log.Println("Write error:", err) break } }}
func main() { http.HandleFunc("/ws", echoHandler) log.Println("Сервер запущен на :8080") log.Fatal(http.ListenAndServe(":8080", nil))}Объяснение кода:
Upgrader— объект, который «повышает» HTTP-соединение до WebSocket.CheckOrigin— функция проверки источника запроса. В продакшене обязательно настройте ее.conn.ReadMessage()иconn.WriteMessage()— основные методы для чтения/записи сообщений.- Цикл
forподдерживает соединение открытым до возникновения ошибки.
Архитектура real-time чата на WebSocket
Эхо-сервер — это основа, но для real-time приложения, например чата, нужна более сложная логика. Рассмотрим архитектуру, где несколько клиентов могут обмениваться сообщениями через сервер.
Основные компоненты:
- Hub — центральный менеджер, хранящий список активных подключений.
- Client — структура, представляющая одно WebSocket-соединение.
- Каналы (channels) — для безопасной передачи данных между горутинами.
package main
import ( "log" "net/http" "github.com/gorilla/websocket")
var upgrader = websocket.Upgrader{ CheckOrigin: func(r *http.Request) bool { return true },}
// Clien