ProgramaciónDesarrollador Go

Explique cómo funciona defer en Go y cuándo el orden de las llamadas puede ser inesperado. ¿Qué trampas se encuentran en la práctica?

Supere entrevistas con el asistente de IA Hintsage

Respuesta.

La palabra clave defer en Go pospone la ejecución de las funciones especificadas hasta la salida de la función envolvente: las funciones se acumulan en una pila y se ejecutan en orden inverso (LIFO). Esto se utiliza a menudo para liberar recursos (archivos, mutex, conexiones).

Una particularidad es que todos los argumentos de las funciones pasadas a defer se evalúan inmediatamente en el momento de la declaración, y no al momento de la ejecución.

func test() { for i := 0; i < 3; i++ { defer fmt.Println(i) // Imprimirá: 2, 1, 0 } }

Pregunta trampa.

¿Qué imprimirá el siguiente código?

func main() { for i := 0; i < 3; i++ { defer fmt.Println(i) } }

Respuesta:

Esto imprimirá:

2
1
0

Porque en cada iteración, el argumento i se evalúa de inmediato (en el momento del defer), y todos los valores se almacenan en la pila de defers.

Ejemplos de errores reales debido al desconocimiento de las sutilezas del tema.


Historia

En un servicio de archivos, olvidaron tener en cuenta que defer se llama solo al salir normalmente de la función. Aparecieron filtraciones, si el programa finalizaba abruptamente antes del punto de llamada a defer.


Historia

En un pipeline de datos ocurrió un olvido: en el ciclo usaron defer para cerrar las conexiones, pero en realidad, se cerraron solo después de que toda la función terminó, y no después de cada iteración. Esto llevó al agotamiento de recursos.


Historia

En el registrador usaron defer con una función anónima, esperando que el argumento se evaluara en el momento de la llamada. Debido a esto, el registro al final contenía información desactualizada, ya que los valores se capturaron antes.