Introducción
El evento Garden Night tiene varias entradas web locales: registro de asistentes, mapa, página del personal e información de entradas. Antes de abrir, sus organizadores necesitan un resultado fiel para cada comprobación asignada. Una entrada que rechace la petición o responda despacio no debe desaparecer del informe.
Completarás una función de comprobación en Go y guardarás un informe JSON real. Debes conocer funciones, estructuras, slices, módulos y la sintaxis básica de canales de Go, además de haber realizado Building a Lost and Found API o tener experiencia equivalente con HTTP. Los errores del cliente HTTP, los tiempos de espera limitados y la responsabilidad sobre la respuesta se explican antes de usarlos. Todos los destinos son servicios locales controlados; esta es una comprobación puntual del evento, no un escáner de Internet ni un servicio de monitorización. Esta unidad es independiente y no necesita archivos de otra VM. Calcula unos 55 minutos, incluida la lectura y los errores habituales; es una estimación del autor.
Lee una comprobación sencilla que funciona
En este paso, ejecutarás un pequeño caso que funciona y aprenderás qué identifica un resultado. Empieza en Workspace. El código Go y el servicio local del evento ya están preparados. Todos los comandos siguientes se ejecutan en Workspace.
cd selecciona el directorio. Go está en /usr/local/go/bin; export añade ese directorio delante del $PATH existente de esta shell. Solo afecta a esta sesión del terminal. Repite ambas líneas al abrir otra shell; no es necesario cambiar archivos globales de configuración.
cd /home/labex/project/site-checker
export PATH=/usr/local/go/bin:$PATH
cat lee archivos sin editarlos. Lee las dos asignaciones normales y las estructuras de datos de Go:
cat normal.json types.go
Cada destino tiene un id que identifica la asignación, una url que se solicitará y want, el texto esperado en el cuerpo de la respuesta. El resultado conserva id y url; kind expresa el resultado de negocio y status es el código HTTP recibido, o cero si no llegaron cabeceras de respuesta. Una asignación es distinta de su URL: dos personas pueden pedir comprobaciones separadas de la misma entrada.
go run . compila y ejecuta el paquete Go de este directorio. El comando preparado acepta -input para una lista JSON, -workers para el máximo de comprobaciones simultáneas y -timeout para el presupuesto de tiempo HTTP de cada destino. 200ms significa 200 milisegundos. Aquí, un worker comprueba las dos entradas rápidas en secuencia. El operador > de la shell envía la salida estándar a un archivo y lo reemplaza si ya existe; los errores siguen apareciendo en el terminal.
go run . -input normal.json -workers 1 -timeout 200ms > normal-report.json
Lee el resultado que realmente se ha guardado:
cat normal-report.json
Ambas asignaciones deben tener kind: "ok" y status: 200, con sus ID y URL originales. 200 indica que el servidor aceptó este GET; por sí solo no demuestra que aparezca el contenido esperado. El primer borrador solo entiende el caso sencillo. Ahora harás que los resultados de las otras entradas también sean útiles.
Si aparece go: command not found, repite el export de la sesión. Si no se encuentra un archivo, repite cd y comprueba su nombre. Si Go informa después de un error de compilación, usa su nombre de archivo y número de línea para localizar y reparar esa pequeña zona. El siguiente paso enseña a editar, guardar y comprobar tus cambios sin sustituir todo el archivo. Conserva sin cambios main.go, types.go, todos los archivos JSON de entrada y el servicio local preparado.
Distingue las respuestas de las peticiones fallidas
En este paso, edita la pequeña función Check en Workspace, una decisión cada vez. Mantén run.go secuencial para centrarte en el significado de un destino. Primero lee el borrador:
cat check.go
El resultado empieza con el ID y la URL de esta asignación. client.Get devuelve una respuesta y un error. La rama de error existente maneja una conexión fallida; una llamada correcta da a esta función la responsabilidad de cerrar el cuerpo de la respuesta. Conserva defer response.Body.Close() inmediatamente después de esa rama de error: defer se ejecuta cuando la función regresa, también en un retorno anticipado. Conserva también la asignación del estado recibido. Ampliarás este borrador en lugar de sustituirlo por un programa terminado suministrado.
Edita y recupérate localmente
Antes de editar, crea una copia del código fuente. cp copia un archivo; la terminación .bak importa porque otro archivo .go se compilaría como parte de este paquete y podría definir Check dos veces.
cp check.go check.go.bak
Abre el archivo existente en el editor del terminal:
nano check.go
En nano, muévete con las flechas. Escribe para insertar texto; Backspace y Delete eliminan caracteres. Ctrl+K corta la línea actual, así que úsalo solo cuando deba eliminarse toda esa línea. Ctrl significa mantener Control mientras pulsas la otra tecla. Usa Ctrl+W, escribe func Check y pulsa Enter para buscar; Ctrl+C cancela una búsqueda. Edita en el cursor. Para guardar, pulsa Ctrl+O, comprueba que el nombre siga siendo check.go y pulsa Enter. Pulsa Ctrl+X para salir. Repite nano check.go cuando necesites otra edición. Si abriste un nombre de archivo incorrecto o hiciste cambios no deseados, pulsa Ctrl+X y después N cuando pregunte si quieres guardar. Ante una pregunta con un nombre de archivo no deseado, Ctrl+C la cancela. Ejecuta pwd para consultar tu directorio, usa el cd del primer paso y abre el archivo correcto antes de intentarlo de nuevo.
Después de cada edición, gofmt -w check.go da formato al archivo en el mismo lugar. Una llave ausente u otro error de sintaxis incluye un nombre de archivo y un número de línea: vuelve a abrir ese archivo, busca la instrucción cercana y repara esa zona. Usa cat check.go después de guardar para inspeccionar lo que realmente está en disco. Conserva las partes que ya funcionan; un error corriente de código no requiere reiniciar la VM ni sobrescribir toda la función.
Decide si el servidor aceptó esta entrada
Una respuesta 403 es un intercambio HTTP correcto, así que Get no devuelve automáticamente un error de Go por ella. Este evento exige exactamente el estado 200; los demás estados recibidos significan http_error. Es la regla de negocio del evento, no una afirmación de que cualquier otro estado 2xx sea universalmente un fallo HTTP.
En Check, después de guardar response.StatusCode, escribe una condición que lo compare con http.StatusOK, la constante de la biblioteca estándar para 200. Para un estado diferente, establece el tipo de resultado en "http_error" y devuelve ese resultado inmediatamente. Conserva por ahora el resultado final "ok" existente. Retornar aquí cierra el cuerpo mediante el defer existente sin esperar a leer un cuerpo de error innecesario.
Guarda, sal de nano y da formato:
gofmt -w check.go
Antes de ejecutar, predice qué deben informar las asignaciones normales y la del personal. Puedes inspeccionar todas las asignaciones sin editarlas:
cat targets.json
go run . -input targets.json -workers 1 -timeout 200ms
En esta fase, la asignación del personal debe ser http_error con 403, mientras que las páginas 200 recibidas siguen siendo ok aunque su contenido sea incorrecto. La comprobación lenta de entradas sigue llamándose connection_error; distinguirás los tiempos agotados más abajo. Estos errores pendientes deliberados muestran qué deben cambiar tus siguientes ediciones. Cada ID de entrada, incluidos ambos ID de registro, debe seguir teniendo un resultado.
Comprueba el contenido de la página recibida
Para una respuesta 200, io.ReadAll(response.Body) devuelve los bytes del cuerpo y un error. Añade io y strings junto a net/http en un grupo de importación: import ( seguido de un nombre de paquete entre comillas por línea y después ). Las importaciones nombran paquetes que usa tu archivo; las importaciones no usadas son errores de compilación, así que añádelas al implementar sus llamadas.
Antes de clasificar un cuerpo recibido correctamente, léelo en body y err. Si la lectura falla, devuelve por ahora un resultado con "connection_error". Conserva el estado ya recibido en el resultado. Después de una lectura correcta, establece o conserva primero result.Kind = "ok". Después, tras esa asignación y antes del retorno final, comprueba el marcador esperado. string(body) convierte los bytes a texto y strings.Contains(string(body), target.Want) indica si ese texto incluye el marcador. Cuando sea falso, cambia el tipo a "content_mismatch". No asignes "ok" de nuevo después de esta condición, o sobrescribirías la discrepancia. En Go, ! niega un booleano. Conserva un único retorno final para el cuerpo leído correctamente.
Guarda y sal; después da formato y repite las mismas asignaciones reales:
gofmt -w check.go
go run . -input targets.json -workers 1 -timeout 200ms
Ahora el mapa incorrecto debe ser content_mismatch con 200, mientras que ambas asignaciones de registro siguen siendo ok con 200 y el resultado del personal sigue siendo http_error con 403. Un estado recibido no demuestra que coincida el marcador. El tiempo agotado de las entradas aún necesita su propia categoría.
Distingue una espera finita de otro fallo
El presupuesto del cliente HTTP incluye la lectura del cuerpo de la respuesta. Un vencimiento antes de las cabeceras deja el estado en cero; uno después de recibir cabeceras 200 debe conservar el estado 200. Añade net a las importaciones. Un net.Error tiene un método Timeout(). Este pequeño patrón Go comprueba si un error admite esa interfaz antes de llamar a su método:
if networkError, ok := err.(net.Error); ok && networkError.Timeout() {
// The operation exceeded its time budget.
}
La aserción de tipo devuelve un valor convertido y un booleano. && evalúa su lado derecho solo si el izquierdo es verdadero. En ambas ramas, la de error de petición y la de error de lectura del cuerpo, conserva "connection_error" como valor predeterminado y cámbialo a "timeout" cuando pase esta comprobación protegida. Conserva el retorno de cada rama y la identidad original de la tarea. Guarda, sal y da formato:
gofmt -w check.go
El servicio existente también ofrece dos casos controlados útiles: /garden/bodylate/check envía cabeceras 200 antes de su demora finita de 600ms en el cuerpo; /garden/deniedbody/check envía cabeceras 403 antes de esa misma demora de cuerpo innecesaria. Crea una entrada complementaria para examinar estos casos y deja intactas todas las listas JSON preparadas:
nano body-probes.json
Introduce este array JSON. JSON usa claves y cadenas entre comillas dobles, comas entre campos y objetos y corchetes alrededor de la lista. No hay coma después del último campo u objeto.
[
{"id": "body-200", "url": "http://127.0.0.1:8080/garden/bodylate/check", "want": "GARDEN OPEN"},
{"id": "body-403", "url": "http://127.0.0.1:8080/garden/deniedbody/check", "want": "GARDEN OPEN"}
]
Guarda con Ctrl+O, confirma body-probes.json y Enter, y sal con Ctrl+X. Lee el archivo real antes de usarlo:
cat body-probes.json
Predice los dos resultados y solicítalos después con un presupuesto de 200ms:
go run . -input body-probes.json -workers 1 -timeout 200ms
Espera que body-200 sea timeout con estado 200 y que body-403 sea http_error con estado 403. El rechazo ya se conoce antes de leer el cuerpo, así que su demora no debe convertirlo en un tiempo agotado. El vencimiento del cliente deja de esperar; el servidor puede terminar su trabajo finito más tarde. No deduzcas la corrección a partir del tiempo total transcurrido.
Por último, vuelve a ejecutar la lista completa original de asignaciones:
go run . -input targets.json -workers 1 -timeout 200ms
Relaciona por ID, no por posición de fila. Espera dos resultados ok, un http_error con 403, un content_mismatch con 200, un timeout con cero y un connection_error con cero. Los fallos de negocio son valores normales del informe, así que el comando sigue terminando correctamente. Un error de compilación o de sintaxis JSON significa que el comando no pudo hacer su trabajo: usa el archivo y la ubicación indicados para reparar tu edición local y después repite ese comando. La comprobación del curso prueba tu código original y el cierre de cuerpos con entradas independientes; no exige un editor concreto ni el nombre del archivo complementario.
Guarda y lee el informe completo
En este paso, guardarás un informe útil sin perder ninguna asignación. Lee el bucle secuencial preparado:
cat run.go
http.Client{Timeout: budget} aplica un presupuesto finito a cada petición. El bucle llama una vez a Check por destino y añade todos los resultados, incluidos los errores. No debe regresar al encontrar la primera entrada fallida ni reunir resultados en un map cuya clave sea la URL. El slice vacío inicializado también genera un array JSON vacío cuando no hay asignaciones.
Guarda ahora el informe completo. Solo se reemplaza intencionadamente el archivo del informe; las asignaciones de entrada quedan intactas.
go run . -input targets.json -workers 1 -timeout 200ms > report.json
Lee el archivo que has generado realmente:
cat report.json
Usa los ID para relacionar las dos tareas de registro con la misma URL. Cada una debe aparecer exactamente una vez. El 403 indica a los organizadores que un servidor respondió y rechazó la petición; no es una interrupción de conexión. El marcador incorrecto del mapa exige investigar el contenido, aunque el estado sea 200. Un tiempo agotado indica que esta comprobación superó su presupuesto, no que el servicio nunca responderá.
Por último, prueba la lista vacía preparada. La salida estándar se muestra directamente, por lo que no reemplaza tu informe útil:
go run . -input empty.json -workers 1 -timeout 200ms
Espera [] y una finalización normal. Conserva report.json, tu check.go actualizado y todas las entradas originales. Las comprobaciones del curso leen este informe y también ejecutan tu código sin modificar contra servicios locales independientes; copiar filas o devolver resultados estáticos no sustituye las peticiones reales.
Resumen
Has creado un resultado fiel para cada entrada local asignada, distinguido rechazos HTTP de fallos de transporte, reconocido contenido incorrecto, aplicado presupuestos HTTP finitos y cerrado todos los cuerpos recibidos. Has guardado y leído un informe JSON completo, conservando las URL repetidas como tareas con ID separados. La siguiente unidad mantiene estas decisiones y cambia cómo comparte el trabajo un grupo pequeño de workers.



