Skip to content

Commit 7380c5a

Browse files
committed
feat: add section on recoverable errors with comparisons between Go and Rust
1 parent 89a3a71 commit 7380c5a

File tree

1 file changed

+114
-0
lines changed

1 file changed

+114
-0
lines changed

src/es/quick-comparisons/error-handling.md

Lines changed: 114 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -178,4 +178,118 @@ De esta forma estamos manejando el posible panico.
178178

179179
---
180180

181+
## Errores recuperables
182+
183+
Cuando hablamos de "Errores recuperables" nos referimos a errores son errores
184+
esperables como pueden ser errores del tipo archivo no encontrado, conexión
185+
rechazada, división por cero, etc.
186+
No son bugs, sino situaciones previstas que el programa puede manejar.
187+
188+
### 🐹 En Go
189+
190+
Go se usa una convención: las funciones devuelven `(T, error)` donde `T` es el
191+
tipo de retorno y `error` es un tipo de error que representa el error
192+
ocurrido, si no hay error, el valor de `error` es `nil`.
193+
Esto es una convención que se sigue en todo el lenguaje, no es obligatorio pero
194+
es la forma más común de manejar errores.
195+
Si la función falla, retorna un error, si no falla, retorna el valor esperado
196+
y `nil` como error.
197+
Esto es una forma de manejar errores que es bastante simple y directa, pero
198+
puede resultar un poco verbosa y repetitiva.
199+
Por ejemplo, si tenemos una función que divide dos números, podría verse así:
200+
201+
```go
202+
#package main
203+
#
204+
#import "fmt"
205+
#
206+
func dividir(a, b int) (int, error) {
207+
if b == 0 {
208+
return 0, fmt.Errorf("división por cero")
209+
}
210+
return a / b, nil
211+
}
212+
#
213+
#func main() {
214+
# resultado, err := dividir(10, 0)
215+
# if err != nil {
216+
# fmt.Println("Error:", err)
217+
# return
218+
# }
219+
# fmt.Println("Resultado:", resultado)
220+
#}
221+
```
222+
223+
Donde si `b` es cero, retornamos un error, si no, retornamos el resultado
224+
y `nil` como error.
225+
226+
### 🦀 En Rust
227+
228+
Rust usa el tipo `Result<T, E>` para manejar errores recuperables, donde `T` es
229+
el tipo de retorno y `E` es el tipo de error.
230+
El tipo `Result` es un enum que puede ser `Ok(T)` o `Err(E)`:
231+
232+
```rust
233+
enum Result<T, E> {
234+
Ok(T),
235+
Err(E),
236+
}
237+
```
238+
239+
Lo que permite manejar errores de forma más explícita y segura, nos garantiza
240+
seguridad, o falla o nos devuelve el resultado esperado pero imposibilita el
241+
obtener ambos valores.
242+
Por ejemplo, si tenemos una función que divide dos números, podría verse así:
243+
244+
```rust
245+
fn dividir(a: i32, b: i32) -> Result<i32, String> {
246+
if b == 0 {
247+
Err("División por cero".to_string())
248+
} else {
249+
Ok(a / b)
250+
}
251+
}
252+
#
253+
#fn main() {
254+
# match dividir(10, 0) {
255+
# Ok(resultado) => println!("Resultado: {}", resultado),
256+
# Err(e) => println!("Error: {}", e),
257+
# }
258+
#}
259+
```
260+
261+
En este caso, si `b` es cero, retornamos un `Err` con un mensaje de error,
262+
si no, retornamos un `Ok` con el resultado de la división.
263+
264+
Es más explicito el path al decir que algo es un error, y no es necesario
265+
retornar un valor adicional como en Go, ya que el `Result` ya nos indica si
266+
hubo un error o no.
267+
268+
En Go funciona como una tupla en Rust como un enum.
269+
270+
Sin embargo en Rust los errores no se pueden ignorar, si no se maneja el
271+
`Result`, el compilador nos dará un error de compilación, lo que nos obliga
272+
a manejar los errores de forma explícita.
273+
274+
Este es el manejo de errores más simple en Rust, y se encuentra en esta sección
275+
porque es facilmente comparable con el manejo de errores en Go.
276+
277+
Sin embargo, Rust tiene un sistema de manejo de errores mucho más avanzado y
278+
flexible que permite manejar errores de forma más eficiente, permitiendo
279+
propagación (una de las funcionalidades más queridas en Go), conversiones de
280+
tipo y dando seguridad en todos los casos, todo esto lo veremos en la sección
281+
de Manejo de Errores Avanzados.
282+
283+
### Comparativa de manejo de errores
284+
285+
Aquí una tabla comparativa entre Rust y Go para el manejo de errores
286+
287+
| | **Rust** | **Go** |
288+
| ------------------------ | --------------------------------- | --------------------------------- |
289+
| ¿Cómo se manejan? | `Result<T, E>` | `(T, error)` |
290+
| ¿Qué tipo de error? | `enum Result<T, E>` | `error` (interfaz) |
291+
| ¿Obliga a manejarlo? | ✅ Sí (el compilador lo exige) | ❌ No (convención `if err != nil`)|
292+
| ¿Qué pasa si lo ignorás? | ⚠️ Warning o error de compilación | 🚫 Nada, se puede ignorar |
293+
| ¿Propagación de errores? || ✅ Con `return` o `defer` |
294+
181295

0 commit comments

Comments
 (0)