Cliente HTTP en Go: haciendo solicitudes correctamente de la A a la Z

Entrenador de Python en Línea para Principiantes

Aprende Python fácilmente sin sobrecargarte de teoría. Resuelve tareas prácticas con verificación automática, recibe pistas y escribe código directamente en el navegador, sin instalar nada.

Start Course

Introducción: Por qué es importante saber trabajar con HTTP en Go

\n

Go (Golang) es un lenguaje creado para trabajar en red. Su biblioteca estándar net/http proporciona herramientas potentes y flexibles para crear tanto servidores como clientes. Sin embargo, muchos desarrolladores, especialmente aquellos que vienen de lenguajes de scripting, cometen errores típicos: olvidan cerrar el cuerpo de la respuesta, no establecen tiempos de espera o manejan incorrectamente los errores.

\n

En este artículo, analizaremos la creación de un cliente HTTP en Go «de la A a la Z». Aprenderá cómo enviar correctamente solicitudes GET y POST, gestionar encabezados, configurar tiempos de espera y manejar errores. Todos los ejemplos de código están listos para usar.

\n\n

1. Fundamentos: creación del cliente y primera solicitud GET

\n

En Go, el cliente HTTP es una estructura http.Client. Puede usar el cliente global http.DefaultClient o crear el suyo propio con configuraciones personalizadas. Comencemos con una solicitud GET simple.

\n
package main\n\nimport (\n    "fmt"\n    "io"\n    "net/http"\n    "os"\n)\n\nfunc main() {\n    // Usamos el cliente incorporado\n    resp, err := http.Get("https://api.example.com/data")\n    if err != nil {\n        fmt.Printf("Error en la solicitud: %v\\n", err)\n        os.Exit(1)\n    }\n    defer resp.Body.Close() // IMPORTANTE: ¡siempre cerrar el cuerpo de la respuesta!\n\n    // Leemos el cuerpo de la respuesta\n    body, err := io.ReadAll(resp.Body)\n    if err != nil {\n        fmt.Printf("Error al leer la respuesta: %v\\n", err)\n        os.Exit(1)\n    }\n\n    fmt.Printf("Estado: %s\\n", resp.Status)\n    fmt.Printf("Cuerpo: %s\\n", string(body))\n}
\n

Puntos clave:

\n
    \n
  • Siempre cierre resp.Body mediante defer. De lo contrario, se producirá una fuga de recursos (las conexiones no volverán al grupo).
  • \n
  • Verifique el estado de la respuesta (resp.StatusCode). El código 200 no es el único exitoso (existen 201, 204, etc.).
  • \n
  • io.ReadAll lee todo el cuerpo en memoria. Para respuestas grandes, use io.Copy o procesamiento por flujo.
  • \n
\n\n

2. Cliente avanzado: tiempos de espera, encabezados y configuraciones personalizadas

\n

El cliente global no tiene tiempos de espera por defecto; esto puede provocar que el programa se cuelgue. Siempre cree su propio cliente con configuraciones.

\n

2.1. Creación de un cliente con tiempo de espera

\n
client := &http.Client{\n    Timeout: 10 * time.Second, // Tiempo de espera total para toda la solicitud\n}\n\nresp, err := client.Get("https://api.example.com/data")
\n

También puede configurar tiempos de espera en diferentes niveles a través de Transport:

\n
transport := &http.Transport{\n    DialContext: (&net.Dialer{\n        Timeout:   5 * time.Second, // Tiempo de espera de conexión\n        KeepAlive: 30 * time.Second,\n    }).DialContext,\n    TLSHandshakeTimeout:   5 * time.Second,\n    ResponseHeaderTimeout: 5 * time.Second,\n}\n\nclient := &http.Client{\n    Transport: transport,\n    Timeout:   15 * time.Second,\n}
\n\n

2.2. Adición de encabezados y parámetros

\n

Para solicitudes complejas, use http.NewRequest:

\n
req, err := http.NewRequest("GET", "https://api.example.com/search", nil)\nif err != nil {\n    log.Fatal(err)\n}\n\n// Agregamos encabezados\nreq.Header.Set("Authorization", "Bearer your-token")\nreq.Header.Set("Accept", "application/json")\n\n// Agregamos parámetros de consulta\nq := req.URL.Query()\nq.Add("query", "golang")\nq.Add("page", "1")\nreq.URL.RawQuery = q.Encode()\n\nresp, err := client.Do(req)
\n\n

3. Trabajo con POST y otros métodos (JSON, formularios)

\n

Las solicitudes POST requieren el envío de un cuerpo. Consideremos dos formatos populares: JSON y formulario codificado en URL.

\n

3.1. POST con JSON

\n
type RequestData struct {\n    Name  string `json:"name"`\n    Email string `json:"email"`\n}\n\ndata := RequestData{\n    Name:  "Iván",\n    Email: "ivan@example.com",\n}\n\njsonData, err := json.Marshal(da                

Blogs

Book Recommendations