Como obter uma resposta HTTP como string em Go: melhores práticas 2025

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

«Access HTTP response as string in Go» — uma pergunta que atormenta iniciantes e profissionais

\n\n

Você já escreveu um cliente HTTP em Go e de repente percebeu que não sabia como transformar elegantemente a resposta bruta do servidor em uma string comum? Se sim — você não está sozinho. A pergunta «Access HTTP response as string in Go» no Stack Overflow acumula milhares de visualizações, e não é por acaso.

\n\n

Go é uma linguagem amada pela sua simplicidade, mas trabalhar com respostas HTTP pode confundir até mesmo um desenvolvedor experiente. Em 2025, as melhores práticas mudaram: o antigo ioutil.ReadAll ficou no passado, e novas abordagens padrão entraram em cena. Vamos entender como ler corretamente uma resposta HTTP como string, evitando erros típicos e seguindo os cânones modernos do Go.

\n\n

Por que simplesmente «ler a resposta» não é tão simples assim?

\n\n

Quando você faz uma requisição HTTP em Go, a resposta chega como um objeto *http.Response. Seu corpo (Body) é um io.ReadCloser, ou seja, um fluxo de bytes que precisa ser lido e interpretado. Se você tentar simplesmente atribuí-lo a uma string, o compilador dirá «não». É necessário ler explicitamente o fluxo para a memória, converter os bytes em string e não esquecer de fechar o corpo.

\n\n

Aqui está um exemplo mínimo que você verá na maioria dos tutoriais (mas vamos melhorá-lo):

\n\n
package main\n\nimport (\n    "fmt"\n    "net/http"\n    "io"\n)\n\nfunc main() {\n    resp, err := http.Get("https://api.example.com/data")\n    if err != nil {\n        panic(err)\n    }\n    defer resp.Body.Close()\n\n    body, err := io.ReadAll(resp.Body)\n    if err != nil {\n        panic(err)\n    }\n\n    fmt.Println(string(body))\n}
\n\n

Funciona. Mas em um projeto real, essa abordagem é um caminho para vazamentos de memória, código ilegível e bugs difíceis de detectar. Vamos analisar o que pode ser melhorado.

\n\n

Melhores práticas 2025: como ler uma resposta HTTP como string corretamente

\n\n

1. Esqueça o ioutil.ReadAll — use io.ReadAll

\n\n

Se você está escrevendo em Go versão 1.16+, esqueça o pacote ioutil. Ele está marcado como deprecated. Em vez disso, use io.ReadAll. Não é apenas uma troca de nome: io.ReadAll funciona mais rápido e de forma mais limpa, e o principal — não requer a importação de um pacote extra.

\n\n
// Ruim (obsoleto)\nimport "io/ioutil"\nbody, _ := ioutil.ReadAll(resp.Body)\n\n// Bom (moderno)\nimport "io"\nbody, _ := io.ReadAll(resp.Body)
\n\n

2. Sempre trate os erros (mesmo que pareça que não há nenhum)

\n\n

Erro ao ler o corpo da resposta não é raro. A rede pode cair, o servidor pode fechar a conexão, ou o corpo pode ser muito grande. Ignorar o erro (_) é prejudicial. Sempre verifique o err:

\n\n
body, err := io.ReadAll(resp.Body)\nif err != nil {\n    // Registramos o erro, retornamos um fallback ou entramos em pânico\n    log.Printf("Erro ao ler o corpo da resposta: %v", err)\n    return "", fmt.Errorf("não foi possível ler a resposta: %w", err)\n}
\n\n

3. Limite o tamanho do corpo da resposta

\n\n

Imagine: você faz uma requisição a uma API, e ela retorna 10 GB de dados. Seu io.ReadAll tentará carregar tudo na memória. O servidor cairá. O cliente travará. O usuário ficará furioso.

\n\n

Solução: use io.LimitReader. Limite o tamanho a um valor razoável (por exemplo, 10 MB):

\n\n
const maxBodySize = 10 * 1024 * 1024 // 10 MB\nlimitedReader := io.LimitReader(resp.Body, maxBodySize)\nbody, err := io.ReadAll(limitedReader)\nif err != nil {\n    // Tratamento do erro\n}
\n\n

Se o corpo da resposta exceder o limite, o io.ReadAll simplesmente lerá os primeiros 10 MB e terminará sem erro. Se você precisar controlar rigorosamente a ultrapassagem — continue lendo, discutiremos isso na seção sobre técnicas avançadas.

\n\n

4. Feche o resp.Body — mas corretamente

\n\n

defer resp.Body.Close() é o padrão. Mas há um detalhe: se você está lendo o corpo

Blogs

Book Recommendations