Long Polling vs WebSocket em Go: A Batalha pelo Tempo Real

Treinador Online de Python para Iniciantes

Aprenda Python facilmente sem sobrecarga teórica. Resolva tarefas práticas com verificação automática e escreva código diretamente no navegador.

Start Course

Introdução: O Dilema do Desenvolvedor

\n\n

Imagine: você está escrevendo um chat, um terminal de ações ou um jogo online em Go. O cliente precisa receber atualizações instantaneamente. O bom e velho AJAX com polling periódico está descartado — muitas requisições inúteis que sobrecarregam tanto o servidor quanto a bateria do usuário. Restam dois candidatos: Long Polling (consulta longa) e WebSocket.

\n\n

Ambos resolvem o problema de "tempo real", mas o fazem de maneiras fundamentalmente diferentes. Qual escolher para sua aplicação Go? Vamos entender sem rodeios, com exemplos de código reais e uma análise honesta dos prós e contras. Este artigo é seu guia no mundo das comunicações em tempo real em Go.

\n\n

O que é Long Polling em Go?

\n\n

Long Polling é uma evolução do polling comum. O cliente envia uma requisição HTTP ao servidor, mas o servidor não responde imediatamente se não houver dados. Ele "congela" (mantém a conexão aberta) e espera até que um novo evento ocorra. Assim que o evento acontece, o servidor envia a resposta e o cliente cria imediatamente uma nova requisição Long Polling. O ciclo se repete.

\n\n

Em Go, isso é implementado de forma muito elegante graças às goroutines e canais. O servidor pode "adormecer" o manipulador da requisição até que os dados estejam disponíveis.

\n\n

Exemplo de servidor Long Polling em Go

\n\n
package main\n\nimport (\n    "fmt"\n    "net/http"\n    "time"\n)\n\n// Canal para receber novas mensagens\nvar messages = make(chan string, 10)\n\nfunc longPollHandler(w http.ResponseWriter, r *http.Request) {\n    select {\n    case msg := <-messages:\n        fmt.Fprintf(w, "Nova mensagem: %s", msg)\n    case <-time.After(30 * time.Second):\n        // Timeout — se nenhuma mensagem chegar em 30 segundos\n        http.Error(w, "Timeout", http.StatusGatewayTimeout)\n    }\n}\n\nfunc main() {\n    // Goroutine simulando o surgimento de novas mensagens\n    go func() {\n        for {\n            time.Sleep(5 * time.Second)\n            messages <- fmt.Sprintf("Hora: %s", time.Now().String())\n        }\n    }()\n\n    http.HandleFunc("/poll", longPollHandler)\n    http.ListenAndServe(":8080", nil)\n}\n
\n\n

O cliente em JavaScript ficará assim: após receber a resposta (ou timeout), ele chama /poll novamente. Simples, confiável, funciona através de qualquer proxy e firewall.

\n\n

WebSocket em Go: Dúplex Completo

\n\n

WebSocket é um protocolo que, após o handshake (HTTP Upgrade), transforma a conexão em um canal bidirecional permanente. O servidor pode enviar dados ao cliente a qualquer momento, e o cliente ao servidor. Sem requisições repetidas, sem timeouts.

\n\n

Em Go, a biblioteca padrão não tem suporte nativo a WebSocket, mas existe o padrão ouro — o pacote gorilla/websocket. Ele é estável, bem documentado e usado em produção por milhares de projetos.

\n\n

Exemplo de servidor WebSocket em Go

\n\n
package main\n\nimport (\n    "log"\n    "net/http"\n    "time"\n\n    "github.com/gorilla/websocket"\n)\n\nvar upgrader = websocket.Upgrader{\n    CheckOrigin: func(r *http.Request) bool {\n        return true // Para desenvolvimento. Em produção — verificar!\n    },\n}\n\nfunc wsHandler(w http.ResponseWriter, r *http.Request) {\n    conn, err := upgrader.Upgrade(w, r, nil)\n    if err != nil {\n        log.Print("Falha no upgrade:", err)\n        return\n    }\n    defer conn.Close()\n\n    // Loop infinito de leitura e escrita\n    for {\n        // Lê mensagem do cliente\n        _, message, err := conn.ReadMessage()\n        if err != nil {\n            log.Println("Erro de leitura:", err)\n            break\n        }\n        log.Printf("Recebido: %s", message)\n\n        // Envia resposta (ou notificação push)\n        err = conn.WriteMessage(websocket.TextMessage, []byte("Servidor: "+time.Now().String()))\n        if err != nil {\n            log.Println("Erro de escrita:", err)\n            break\n        }\n    }\n}\n\nfunc main() {\n    http.HandleFunc("/ws", wsHandler)\n    log.Pr                

Blogs

Book Recommendations