Servidor de rede em Go: do TCP ao HTTP em uma noite

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

Por que Go é a linguagem ideal para programação de rede?

\n\n

Se você já escreveu um servidor de rede em Python (especialmente usando socket ou asyncio), sabe como o código pode rapidamente se transformar em um labirinto de callbacks e loops de eventos. Go (Golang) resolve esse problema no nível arquitetural: goroutines e canais tornam o trabalho assíncrono com rede tão simples quanto escrever código sequencial.

\n\n

Neste artigo, vamos explorar a programação de rede em Go na prática. Você aprenderá como montar um chat TCP completo, enviar um pacote UDP e iniciar um servidor HTTP com roteamento em apenas 15 minutos. Todos os exemplos são funcionais — você pode copiá-los e executá-los.

\n\n

Fundamentos: o pacote net e seu superpoder

\n\n

Em Go, toda a mágica de rede está no pacote padrão net. Ele fornece uma interface unificada para trabalhar com TCP, UDP, sockets Unix e até SSL/TLS. O grande diferencial é que as funções Listen, Dial e Accept funcionam de forma síncrona, mas não bloqueiam todo o programa, porque cada goroutine é leve.

\n\n

Vamos direto ao ponto.

\n\n

Servidor TCP: um chat em 10 linhas

\n\n

Vamos criar um simples servidor echo, que aceita conexões e envia de volta o que recebeu. Isso é um clássico da programação de rede em Go.

\n\n
package main\n\nimport (\n    "bufio"\n    "fmt"\n    "net"\n)\n\nfunc handleConnection(conn net.Conn) {\n    defer conn.Close()\n    scanner := bufio.NewScanner(conn)\n    for scanner.Scan() {\n        message := scanner.Text()\n        fmt.Printf("Recebido: %s\\n", message)\n        conn.Write([]byte("Echo: " + message + "\\n"))\n    }\n}\n\nfunc main() {\n    listener, _ := net.Listen("tcp", ":8080")\n    fmt.Println("Servidor TCP rodando na porta :8080")\n    for {\n        conn, _ := listener.Accept()\n        go handleConnection(conn) // cada goroutine é um cliente separado\n    }\n}
\n\n

O que está acontecendo aqui?

\n
    \n
  • net.Listen("tcp", ":8080") — cria um listener TCP na porta 8080.
  • \n
  • O loop infinito for aceita novas conexões via Accept().
  • \n
  • Cada conexão é tratada em uma goroutine separada go handleConnection().
  • \n
  • Dentro da função, lemos linhas com bufio.Scanner e enviamos a resposta.
  • \n
\n\n

Execute este código, abra um terminal e conecte-se via nc localhost 8080 (ou Putty). Qualquer mensagem enviada retornará com o prefixo "Echo:". Incrivelmente, este já é um servidor de rede completo, capaz de atender milhares de clientes sem um único callback.

\n\n

UDP: entrega rápida sem garantias

\n\n

Se TCP é como uma chamada telefônica (conexão estabelecida — conversamos), UDP é como enviar cartões postais: você manda e esquece. Go torna o trabalho com UDP igualmente simples.

\n\n

Cliente e servidor UDP

\n\n
// Servidor\npackage main\n\nimport (\n    "fmt"\n    "net"\n)\n\nfunc main() {\n    addr, _ := net.ResolveUDPAddr("udp", ":8081")\n    conn, _ := net.ListenUDP("udp", addr)\n    defer conn.Close()\n\n    buffer := make([]byte, 1024)\n    for {\n        n, clientAddr, _ := conn.ReadFromUDP(buffer)\n        message := string(buffer[:n])\n        fmt.Printf("Recebido de %s: %s\\n", clientAddr, message)\n        conn.WriteToUDP([]byte("Recebido: "+message+"\\n"), clientAddr)\n    }\n}\n\n// Cliente\n// Em um arquivo separado ou goroutine:\nconn, _ := net.Dial("udp", "localhost:8081")\ndefer conn.Close()\nconn.Write([]byte("Olá, UDP!"))\nbuffer := make([]byte, 1024)\nn, _ := conn.Read(buffer)\nfmt.Println(string(buffer[:n]))
\n\n

Diferença chave do TCP:

\n
    \n
  • Não há Accept() — apenas escutamos a porta e lemos datagramas.
  • \n
  • Cada pacote chega com o endereço do remetente.
  • \n
  • O Go gerencia o buffer automaticamente: ReadFromUDP retorna o endereço de quem enviou.
  • \n

Blogs

Book Recommendations