Lecciones del módulo (2/5)
Retornos múltiples y retornos con nombre
En Go, una función puede devolver múltiples valores. Es el mecanismo que
habilita el patrón (value, error) que ya has visto y que impregna
toda la biblioteca estándar.
Múltiples devoluciones
Los tipos de devolución van entre paréntesis, separados por comas:
func divmod(a, b int) (int, int) {
return a / b, a % b
}
q, r := divmod(17, 5) // q=3, r=2Están desestructurados con asignación múltiple. Para descartar uno de los
los valores usan _:
_, r := divmod(17, 5) // solo il restoEl patrón (T, error) canónico
Casi todo el stdlib lo sigue. error SIEMPRE es el último:
func read(path string) ([]byte, error) {
data, err := os.ReadFile(path)
if err != nil {
return nil, fmt.Errorf("read %q: %w", path, err)
}
return data, nil
}Devoluciones nombradas
Puede nombrar los valores de retorno: se convierten en variables predeclaradas
inicializado a cero, y return sin argumentos los devuelve ("desnudos
devolver"):
func divmod(a, b int) (q, r int) {
q = a / b
r = a % b
return // naked: ritorna q, r
}Las devoluciones con nombre también aparecen en la información sobre herramientas de la documentación, por lo que son útiles como una forma de documentación en línea para funciones complejas, no solo para el regreso desnudo.
¿Más de dos devoluciones?
Nada te impide (int, int, int, error), pero si sientes la necesidad
casi siempre es una señal de que debes devolver una estructura:
type Result struct {
Sum int
Avg float64
Max int
}
func analyze(nums []int) (Result, error) { ... }Pruébalo
Defina divmod(a, b int) (int, int) que devuelva el cociente y el resto.
Mostrar pista
Tipos de retorno entre paréntesis: `(int, int)`.
Solución disponible después de 3 intentos
Implementar safeDiv(a, b int) (int, error): si b == 0 devuelve (0, errores.New('división por cero')), en caso contrario (a/b, nil).
Mostrar pista
Error SIEMPRE como último valor. En caso de error: valor cero + error.
Solución disponible después de 3 intentos
¿Qué imprime este programa utilizando devoluciones con nombre?
func f() (a, b int) {
a = 1
b = 2
return
}
x, y := f()
fmt.Println(x, y)Resumen
- Múltiples valores entre paréntesis:
func f() (T1, T2, error). - Convención:
errorSIEMPRE como último valor; en caso de error, valor cero + error. - Los retornos con nombre declaran previamente las variables y habilitan retornos desnudos.
- Retornos desnudos sólo en funciones muy cortas; más allá de eso, la legibilidad se ve afectada.
- ¿Más de 2-3 devoluciones? Probablemente quieras una estructura.