En Go, prevenir pánicos en producción no empieza con un recover diferido, sino con programación defensiva: validar entradas, límites y punteros antes de desreferenciarlos. Sin embargo, un número creciente de comprobaciones de nil en el código —incluido el generado por IA— suele ser síntoma de que el programa ha perdido trazabilidad sobre el linaje de sus objetos: no se sabe de dónde procede el puntero, quién debía inicializarlo ni qué invariante hacía imposible el nil.
El artículo lo ilustra con un RateLimiter que guarda un cliente Redis. Si se construye con un puntero nil, el error ocurrió antes, en la fase de inicialización; comprobarlo dentro del método Allow no resuelve nada, solo trata un estado inválido como aceptable. La alternativa correcta es fallar rápido y temprano: manejar el error en el sitio de inicialización y, si el almacén puede no estar disponible, modelar esa indisponibilidad explícitamente mediante un envoltorio que sea siempre no nil y gestione reintentos o degradación. Esto replica a nivel de runtime la misma idea de las restricciones NOT NULL en bases de datos: si la invariante se establece en el origen, las capas internas pueden confiar en los datos sin repetir comprobaciones.
El texto advierte también sobre el coste de los fallos silenciosos. Tragar un error o sustituirlo por un nil check para evitar «tirar el programa» es un falso dilema: lo que se gana en robustez aparente se paga después con métricas, paneles y alertas para reconstruir la señal perdida, además de con bugs difíciles de atribuir. La responsabilidad del error debe seguirse hasta la frontera de manejo adecuada. Por último, la pieza distingue entre dependencias —fijas en la construcción— y datos asociados a una petición —que llegan del exterior en cada llamada—. En ambos casos, la comprobación de nil pertenece a la capa externa, en el límite de transporte, no en funciones internas que revalidan lo que el código superior ya debería haber garantizado.
