# GO Recover

En Go, el manejo de errores es un aspecto crucial del desarrollo de software robusto. Junto con `panic`, Go proporciona la función `recover`, que se utiliza para manejar y recuperar errores graves que de otra manera terminarían el programa.

`recover` es una herramienta poderosa que permite capturar un `panic` y evitar que el programa se detenga abruptamente.

#### **¿Qué es recover en Go?**

`recover` es una función incorporada en Go que se utiliza para manejar un `panic` dentro de una función diferida (`defer`). Cuando se invoca dentro de una función `defer`, `recover` detiene el proceso de desenrollado de la pila que ocurre durante un `panic` y devuelve el valor pasado al `panic`. Si `recover` se llama fuera de una función diferida o si no hay un `panic` activo, `recover` simplemente devuelve `nil`.

```go
package main

import "fmt"

func main() {
     // Imprimir mensaje de inicio
     fmt.Println("Inicio del programa")

    // Definir un bloque defer para recuperar de un panic
    defer func() {
        if r := recover(); r != nil {
            fmt.Println("Recuperado de:", r) // Manejar el panic
        }
    }()

    // Generar un panic
    panic("¡Ocurrió un error grave!") // Esto detiene la ejecución normal

    // Esta línea nunca se ejecutará porque el panic interrumpe el flujo
    fmt.Println("Esto no se imprimirá")
}
```

**Explicación del Código:**

1. **`defer func() { if r := recover(); r != nil { fmt.Println("Recuperado de:", r) } }()`:** Este bloque `defer` se ejecutará al final de la función `main`, justo después de que se desencadene un `panic`. Aquí, `recover` se utiliza para capturar el valor pasado al `panic` y manejarlo.
2. **`panic("¡Ocurrió un error grave!")`:** Se genera un `panic`, lo que provoca que la ejecución del programa se detenga y comience a desenrollarse la pila de llamadas.
3. **`fmt.Println("Esto no se imprimirá")`:** Esta línea nunca se ejecutará porque el `panic` interrumpe el flujo antes de que se llegue a ella.

**Salida esperada:**

```
Inicio del programa
Recuperado de: ¡Ocurrió un error grave!
```

#### **¿Cuándo Usar recover?**

El uso de `recover` es adecuado en situaciones donde deseas manejar de manera segura y controlada errores graves que no deberían terminar todo el programa. Por ejemplo, es útil en servidores web o aplicaciones que deben continuar operando incluso si se encuentran con errores graves en ciertas peticiones o procesos.

#### **Ejemplo Práctico: Servidor Web Resiliente**

Imagina que estás construyendo un servidor web en Go y quieres asegurarte de que si una solicitud provoca un `panic`, el servidor no se detenga, sino que maneje el error y continúe funcionando:

```go
package main

import (
    "fmt"
    "net/http"
)

func handleRequest(w http.ResponseWriter, r *http.Request) {
    defer func() {
        if r := recover(); r != nil {
            fmt.Println("Recuperado en handleRequest:", r)
            http.Error(w, "Ocurrió un error interno", http.StatusInternalServerError)
        }
    }()

    // Simular un error
    panic("¡Fallo inesperado en la solicitud!")
}

func main() {
    http.HandleFunc("/", handleRequest)
    fmt.Println("Servidor iniciado en :8080")
    if err := http.ListenAndServe(":8080", nil); err != nil {
        panic(err)
    }
}
```

**Explicación del Código:**

1. **`defer func() { if r := recover(); r != nil { ... } }()`:** Este bloque diferido en `handleRequest` captura cualquier `panic` que ocurra durante la ejecución de la función, asegurando que el servidor pueda continuar manejando otras solicitudes.
2. **`panic("¡Fallo inesperado en la solicitud!")`:** Simula un error grave que normalmente terminaría el programa, pero que en este caso es capturado y manejado.
3. **`http.Error(w, "Ocurrió un error interno", http.StatusInternalServerError)`:** Después de capturar el `panic`, se envía una respuesta HTTP al cliente informando del error interno, en lugar de detener el servidor.

**Salida esperada en la consola del servidor:**

```
Servidor iniciado en :8080
Recuperado en handleRequest: ¡Fallo inesperado en la solicitud!
```

* `http.Error(w, "Ocurrió un error interno", http.StatusInternalServerError)` Se ejecuta igualmente para informar al cliente el error interno de esta forma se maneja el error y no queda paralizada la función.

### **Limitaciones de recover**

Es importante recordar que `recover` solo funciona si se invoca dentro de una función diferida. No puede detener un `panic` si se llama directamente en el flujo normal de la ejecución. Además, el uso excesivo de `recover` para «ocultar» errores puede llevar a un código difícil de mantener y depurar. Debe utilizarse con cuidado y solo en situaciones donde sea absolutamente necesario.

#### **Ejemplo Avanzado: Uso de `recover` en Funciones Reutilizables**

```go
package main

import (
    "fmt"
)

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

func main() {
    safeExecute(func() {
        fmt.Println("Ejecutando una operación segura")
        panic("¡Error en la operación!")
    })

    fmt.Println("El programa sigue corriendo")
}
```

**Explicación del Código:**

1. **`safeExecute`:** Esta función encapsula el patrón `defer-recover`, permitiendo que cualquier función pasada como argumento pueda ser ejecutada de manera segura.
2. **`safeExecute(func() { ... })`:** Aquí se pasa una función anónima que provoca un `panic`, el cual es capturado y manejado por `recover`.

> **Funciones de Orden Superior**: La función `safeExecute` es un ejemplo de una **función de orden superior**, ya que toma otra función como argumento y puede operar sobre ella (en este caso, ejecutarla y manejar posibles panics).

**Salida esperada:**

```

Ejecutando una operación segura
Recuperado de un panic: ¡Error en la operación!
El programa sigue corriendo
```

Y así es como vemos que el error fue manejado y de igual manera la función sigue corriendo

### **Conclusión**

`recover` es una herramienta vital en Go para manejar situaciones excepcionales de manera segura. Cuando se utiliza junto con `panic` y `defer`, te permite capturar errores graves y decidir cómo proceder sin detener todo el programa. Sin embargo, debe usarse con moderación y solo en contextos donde realmente se necesita controlar errores críticos sin detener la ejecución global del programa.
