panic, recover y defer
Cuándo usar panic y cómo recuperarse correctamente
panic, recover y defer es una lección gratuita de Go Academy en CoddyKit. Esta es la lección 4 de 4. Puedes leer la lección completa abajo gratuitamente — luego la practicas en el navegador con un editor de código integrado y un tutor de IA 24/7. Forma parte de la ruta de aprendizaje de Go Academy, y tu progreso se sincroniza en la web y la app de CoddyKit. El curso de Go Academy incluye 4 lecciones en total.
¿Qué es panic?
panic detiene la ejecución normal de la goroutine actual, deshace la pila de llamadas ejecutando las funciones aplazadas y bloquea el programa si no se recupera:
package main
import "fmt"
func mustPositive(n int) int {
if n <= 0 {
panic(fmt.Sprintf("mustPositive: got %d", n))
}
return n
}
func main() {
fmt.Println(mustPositive(5)) // 5
// fmt.Println(mustPositive(-1)) // panics!
}Cuándo utilizar panic
Utilice panic únicamente para:
- Errores de programación verdaderamente irrecuperables (invariantes incumplidas)
- Condiciones imposibles que indiquen un error
- Fallos durante el inicio (configuración ausente, conexiones fallidas durante la inicialización)
No utilice nunca panic para condiciones de fallo previstas; utilice error en su lugar.
Conceptos básicos de defer
defer programa una llamada de función para que se ejecute cuando la función envolvente devuelva el control, independientemente de cómo lo haga (normalmente, con un error o mediante panic):
package main
import "fmt"
func main() {
defer fmt.Println("third")
defer fmt.Println("second") // LIFO order
defer fmt.Println("first")
fmt.Println("running...")
// Output:
// running...
// first
// second
// third
}defer para la limpieza
El uso más habitual de defer es garantizar la liberación de recursos:
package main
import ("fmt"; "os")
func readFile(path string) (string, error) {
f, err := os.Open(path)
if err != nil {
return "", fmt.Errorf("open: %w", err)
}
defer f.Close() // always runs, even if we return early
buf := make([]byte, 1024)
n, _ := f.Read(buf)
return string(buf[:n]), nil
}recover: capturar panics
recover detiene un panic y devuelve su valor. Debe llamarse directamente dentro de una función defer:
package main
import "fmt"
func safeDiv(a, b int) (result int, err error) {
defer func() {
if r := recover(); r != nil {
err = fmt.Errorf("recovered from panic: %v", r)
}
}()
return a / b, nil // panics if b==0
}
func main() {
r, err := safeDiv(10, 0)
fmt.Println(r, err)
// 0 recovered from panic: runtime error: integer divide by zero
}recover debe estar en una función aplazada
recover solo funciona si se llama directamente dentro de una función aplazada. Si se llama en otro lugar, devuelve nil:
package main
import "fmt"
func wrong() {
// recover() here does nothing — not in defer
}
func correct() {
defer func() {
if r := recover(); r != nil {
fmt.Println("caught:", r)
}
}()
panic("oops")
}
func main() { correct() }panic en código de biblioteca
El código de biblioteca casi nunca debe permitir que los panics lleguen a los llamadores. Convierta los panics en errores en el límite:
package main
import ("fmt"; "runtime/debug")
func safeCall(fn func()) (err error) {
defer func() {
if r := recover(); r != nil {
err = fmt.Errorf("panic: %v\n%s", r, debug.Stack())
}
}()
fn()
return nil
}
func main() {
err := safeCall(func() { panic("boom") })
fmt.Println(err != nil) // true
}Orden LIFO de defer y problema en bucles
Las llamadas aplazadas se ejecutan en orden de último en entrar, primero en salir (LIFO). Tenga cuidado al usar defer dentro de bucles; utilice un cierre o una función auxiliar:
package main
import "fmt"
func processFiles(names []string) {
for _, name := range names {
name := name // capture loop variable
defer func() { fmt.Println("close:", name) }()
}
}
func main() {
processFiles([]string{"a.txt", "b.txt", "c.txt"})
// Output (LIFO): close: c.txt, close: b.txt, close: a.txt
}defer con valores de retorno con nombre
Las funciones aplazadas pueden leer y modificar valores de retorno con nombre, lo que resulta útil para anotar errores:
package main
import "fmt"
func doWork() (err error) {
defer func() {
if err != nil {
err = fmt.Errorf("doWork: %w", err)
}
}()
return fmt.Errorf("something failed")
}
func main() {
err := doWork()
fmt.Println(err) // doWork: something failed
}panic frente a error: guía de decisión
Cómo elegir entre panic y error:
- Utilice error: fallos previstos (archivo no encontrado, tiempo de espera de red, entrada no válida)
- Utilice panic: errores de programación (acceso a un mapa nil, índice fuera de rango), estados imposibles y fallos de inicialización
- No utilice nunca panic a través de los límites de una API; los llamadores no pueden gestionarlo
- Recupere los panics en el nivel superior de las goroutines de los servidores para evitar bloqueos
Comprobación rápida
¿Dónde debe llamarse a recover() para capturar un panic?
Repaso: panic, recover y defer
Resumen:
panic: desenrolla la pila, ejecuta las funciones diferidas y provoca un fallo si no se recuperadefer: se ejecuta al salir de la función (normalmente, por error o porpanic); en orden LIFOrecover: detiene elpanicy devuelve un valor; debe estar en una funcióndefer- Use
panicpara errores del programador, no para fallos esperados - Convierta los
panicen errores en los límites de la API
Preguntas frecuentes
¿La lección «panic, recover y defer» es gratis?
Sí — el texto completo de «panic, recover y defer» es gratis para leer aquí en la web. Para practicarla de forma interactiva (editor de código integrado y tutor de IA 24/7) y desbloquear el resto del curso de Go Academy, actualiza a CoddyKit PRO. El curso de Go Academy incluye 4 lecciones en total.
¿Qué aprenderé en «panic, recover y defer»?
Cuándo usar panic y cómo recuperarse correctamente Practicas Go Academy con código real que ejecutas directamente en el navegador, y un tutor de IA 24/7 responde tus preguntas mientras trabajas en la lección.
¿Necesito experiencia previa para empezar Go Academy?
No se requiere experiencia previa. Go Academy en CoddyKit está estructurado para principiantes hasta estudiantes avanzados, así que puedes empezar aquí o desde el inicio y avanzar a tu ritmo. Esta es la lección 4 de 4.
¿Cuánto tiempo toma la lección «panic, recover y defer»?
La mayoría de las lecciones de CoddyKit toman alrededor de 5–10 minutos. Cada una es compacta e interactiva, así que avanzas constantemente y retomas exactamente por donde dejaste en la web y la app.
¿Puedo escribir y ejecutar código en esta lección de Go Academy?
Sí. Cada lección de Go Academy incluye un editor de código integrado, así que escribes y ejecutas código real directamente en tu navegador y obtienes retroalimentación instantánea de IA — sin configuración local necesaria.
Todas las lecciones de este curso
- La interfaz error
- Creación de errores personalizados
- Envoltorio y desenvoltorio de errores
- panic, recover y defer