Introdução: por que o HTTP Client em Go merece atenção
Aplicações web modernas raramente funcionam isoladamente. Praticamente qualquer serviço interage com APIs externas, microsserviços ou recursos de terceiros via HTTP. A linguagem Go (Golang) fornece uma biblioteca nativa poderosa net/http, que permite criar clientes HTTP eficientes e performáticos sem dependências externas.
Neste artigo, vamos abordar como trabalhar corretamente com o HTTP Client em Go: desde requisições GET simples até tratamento de erros e gerenciamento de timeouts. Você aprenderá como evitar erros comuns e escrever código confiável.
Fundamentos do HTTP Client em Go
A biblioteca net/http em Go foi projetada com foco em performance. Diferente de muitas outras linguagens, onde cada requisição cria uma nova conexão, Go utiliza um pool de conexões (connection pool) por padrão. Isso significa que as conexões TCP são reutilizadas, acelerando significativamente o trabalho.
Requisição GET simples
Vamos começar com o exemplo mais simples — enviar uma requisição GET usando a função http.Get():
package main
import ( "fmt" "io" "net/http" "os")
func main() { // Requisição GET simples resp, err := http.Get("https://api.github.com") if err != nil { fmt.Printf("Erro ao executar requisição: %v", err) os.Exit(1) } defer resp.Body.Close()
// Lê o corpo da resposta body, err := io.ReadAll(resp.Body) if err != nil { fmt.Printf("Erro ao ler resposta: %v", err) os.Exit(1) }
fmt.Printf("Status: %s", resp.Status) fmt.Printf("Corpo da resposta: %s", string(body))}Importante: sempre feche o corpo da resposta (resp.Body.Close()). Use defer para garantir o fechamento, mesmo se ocorrer um erro.
Requisição GET com parâmetros e cabeçalhos
Para requisições mais complexas, é melhor usar a sintaxe completa com a criação do objeto http.Request:
package main
import ( "fmt" "io" "net/http" "time")
func main() { // Cria um novo cliente client := &http.Client{ Timeout: 10 * time.Second, }
// Cria a requisição req, err := http.NewRequest("GET", "https://api.example.com/users", nil) if err != nil { fmt.Printf("Erro ao criar requisição: %v", err) return }
// Adiciona cabeçalhos req.Header.Set("Authorization", "Bearer your-token-here") req.Header.Set("Accept", "application/json") req.Header.Set("User-Agent", "Go-http-client/1.0")
// Adiciona parâmetros de query q := req.URL.Query() q.Add("limit", "10") q.Add("offset", "0") req.URL.RawQuery = q.Encode()
// Executa a requisição resp, err := client.Do(req) if err != nil { fmt.Printf("Erro ao executar requisição: %v", err) return } defer resp.Body.Close()
body, _ := io.ReadAll(resp.Body) fmt.Printf("Resposta: %s", string(body))}Trabalhando com requisições POST e JSON
Requisições POST com corpo JSON são uma tarefa padrão ao trabalhar com REST APIs. Go oferece ferramentas convenientes para serialização de dados.
Enviando JSON com POST
package main
import ( "bytes" "encoding/json" "fmt" "net/http" "time")
type User struct { Name string `json:"name"` Email string `json:"email"` Age int `json:"age"`}
func main() { user := User{ Name: "Ivan Petrov", Email: "ivan@example.com", Age: 30, }
// Serializa a estrutura em JSON jsonData, err := json.Marshal(user) if err != nil { fmt.Printf("Erro ao serializar JSON: %v", err) return }
client := &http.Client{Timeout: 5 * time.Second}