Cliente HTTP em Go: técnicas avançadas de trabalho com requisições

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

Cliente HTTP em Go: fazendo requisições corretamente (nível avançado)

O pacote embutido net/http em Go oferece capacidades poderosas, mas frequentemente subestimadas, para criar clientes HTTP confiáveis. No nível inicial, os desenvolvedores usam http.Get ou http.Post, o que é conveniente para protótipos rápidos, mas completamente inadequado para produção. Neste artigo, vamos abordar técnicas avançadas de configuração do cliente HTTP em Go: ajuste fino de timeouts, gerenciamento do pool de conexões, criação de cadeias de middleware, implementação de retries e tratamento adequado de erros. Você aprenderá a escrever código de cliente que suporta altas cargas e é resiliente a falhas de rede.



1. Configuração de timeouts e pool de conexões

O erro básico é usar http.DefaultClient. Ele não tem timeouts e pode ficar pendurado indefinidamente. Para produção, sempre crie sua própria instância de http.Client com ajuste fino de http.Transport.

package main

import ( "net/http" "time")

func NewClient() *http.Client { transport := &http.Transport{ MaxIdleConns: 100, // Máximo de conexões ociosas em todo o pool MaxConnsPerHost: 10, // Máximo de conexões para um único host MaxIdleConnsPerHost: 5, // Máximo de conexões ociosas para um único host IdleConnTimeout: 90 * time.Second, // Tempo de vida da conexão ociosa DisableCompression: false, // Ativamos compressão (gzip) }

client := &http.Client{ Transport: transport, Timeout: 30 * time.Second, // Timeout total para toda a requisição } return client}

Vamos analisar os parâmetros principais:

  • Timeout — limite total de tempo para executar a requisição (incluindo leitura do corpo da resposta). Defina-o de acordo com a velocidade esperada da API (geralmente 10-30 segundos).
  • MaxIdleConns — número de conexões keep-alive armazenadas no pool. Para sistemas de alta carga, aumente para 200-500.
  • MaxConnsPerHost — limita o número de conexões simultâneas para um único host. Previne sobrecarga do servidor.

Também é recomendado configurar DialContext com um timeout próprio para estabelecimento de conexão:

transport.DialContext = (&net.Dialer{    Timeout:   5 * time.Second,  // Timeout para o handshake TCP    KeepAlive: 30 * time.Second, // Keep-alive para manter a conexão}).DialContext


2. Criação de cadeias de middleware para o cliente HTTP

Em Go não há middleware embutido para o cliente, mas podemos facilmente implementar o padrão "decorator" através de um wrapper de http.RoundTripper. Isso permite adicionar logging, métricas, autenticação e outras funções transversais.

type LoggingRoundTripper struct {    Proxied http.RoundTripper}

func (l *LoggingRoundTripper) RoundTrip(r *http.Request) (*http.Response, error) { start := time.Now() resp, err := l.Proxied.RoundTrip(r) duration := time.Since(start)

log.Printf("[%s] %s %s - %d (%v)", r.Method, r.URL.String(), r.Host, resp.StatusCode, duration, ) return resp, err}

// Uso:transport := &LoggingRoundTripper{ Proxied: http.DefaultTransport,}client := &http.Client{Transport: transport}

Podemos criar uma cadeia de middleware, por exemplo, para adicionar cabeçalhos de autenticação:

type AuthRoundTripper struct {    Proxied http.RoundTripper    Token   string}

func (a *AuthRoundTripper) RoundTrip(r *http.Request) (*http.Response, error) { r.Header.Set("Authorization", "Bearer "+a.Token) return a.Proxied.RoundTrip(r)}

// Cadeia: Auth → Logging → Transportclient := &http.Client{ Transport: &LoggingRoundTripper{

Blogs

Book Recommendations