👁️GO Defer

El concepto de defer en Go es una característica poderosa y única del lenguaje que permite postergar la ejecución de una función hasta que la función que la contiene esté a punto de finalizar.

Esto es particularmente útil para tareas de limpieza, como cerrar archivos, liberar recursos, o manejar bloqueos.

Una función diferida en Go es una función que se programa para ejecutarse después de que la función que la contiene haya finalizado, independientemente de cómo termine esa función (ya sea de forma normal o debido a un panic). Esto se logra utilizando la palabra clave defer.

Comportamiento de defer:

  • Las funciones diferidas se ejecutan justo antes de que la función que las contiene retorne.

  • Incluso si ocurre un panic en la función que las contiene, las funciones diferidas aún se ejecutarán.

  • Las funciones diferidas se ejecutan en orden inverso al que fueron declaradas (last in, first out).

¿Qué es defer?

La palabra clave defer se utiliza para diferir la ejecución de una función hasta que la función que la contiene termine su ejecución.

No importa si la función termina normalmente, por un retorno explícito o debido a un panic, las llamadas diferidas se ejecutarán en cualquier caso.

Sintaxis Básica

package main

import (
    "fmt"
)

func main() {
    fmt.Println("Inicio del programa")
    defer fmt.Println("Este mensaje se mostrará al final")
    fmt.Println("Fin del programa")
}

Explicación del Código:

  1. fmt.Println("Inicio del programa"): Esta línea se ejecuta inmediatamente y muestra «Inicio del programa».

  2. defer fmt.Println("Este mensaje se mostrará al final"): La ejecución de esta línea se difiere hasta justo antes de que main finalice. Esto asegura que la función fmt.Println se ejecutará al final.

  3. fmt.Println("Fin del programa"): Esta línea se ejecuta inmediatamente después de la anterior.

Salida esperada:

Inicio del programa
Fin del programa
Este mensaje se mostrará al final

Uso de defer en el Manejo de Recursos

Un uso común de defer es el manejo de recursos como archivos o conexiones de red, asegurando que se liberen correctamente después de su uso.

package main

import (
    "fmt"
    "os"
)

func main() {
    file, err := os.Open("archivo.txt")
    if err != nil {
        fmt.Println("Error al abrir el archivo:", err)
        return
    }
    defer file.Close() // Asegura que el archivo se cierre al final de la función

    // Leer y procesar el archivo aquí

    fmt.Println("Archivo abierto exitosamente")
}

Explicación del Código:

  1. file, err := os.Open("archivo.txt"): Se intenta abrir un archivo llamado archivo.txt. Si ocurre un error, se muestra un mensaje y se sale de la función.

  2. defer file.Close(): Si el archivo se abre correctamente, defer se asegura de que el archivo se cierre al final de la función, independientemente de cómo termine la ejecución.

  3. fmt.Println("Archivo abierto exitosamente"): Se ejecuta si el archivo se abre sin problemas.

Orden de Ejecución de Múltiples defer

Si se utilizan varias instrucciones defer, estas se ejecutan en orden inverso al que fueron declaradas (LIFO: Last In, First Out).

package main

import (
    "fmt"
)

func main() {
    defer fmt.Println("Primero en diferir, último en ejecutarse")
    defer fmt.Println("Segundo en diferir")
    defer fmt.Println("Tercero en diferir, primero en ejecutarse")
}

Salida esperada:

Tercero en diferir, primero en ejecutarse
Segundo en diferir
Primero en diferir, último en ejecutarse

Ejemplo Avanzado: Uso de defer con panic y recover

El uso de defer junto con panic y recover permite manejar errores y excepciones de forma controlada.

package main

import (
    "fmt"
)

func main() {
    defer func() {
        if r := recover(); r != nil {
            fmt.Println("Recuperado de:", r)
        }
    }()

    fmt.Println("Ejecutando función principal")
    panic("¡Algo salió mal!")
    fmt.Println("Esto no se imprimirá")
}

Explicación:

  1. defer func() { if r := recover(); r != nil { fmt.Println("Recuperado de:", r) } }: Este defer utiliza recover para capturar un panic y manejarlo de manera segura.

  2. panic("¡Algo salió mal!"): Lanza un panic, deteniendo la ejecución normal del programa.

  3. fmt.Println("Esto no se imprimirá"): Esta línea nunca se ejecuta debido al panic.

Salida esperada:

Ejecutando función principal
Recuperado de: ¡Algo salió mal!

Conclusión

Además, la combinación de defer con panic y recover proporciona un mecanismo robusto para el manejo de excepciones, haciendo de Go un lenguaje seguro y fiable para el desarrollo de software.

Last updated