Saltar al contenido principal
eLearner.app
Módulo 3 · Lección 2 de 512/50 en el curso~12 min
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:

Go
func divmod(a, b int) (int, int) {
    return a / b, a % b
}

q, r := divmod(17, 5) // q=3, r=2

Están desestructurados con asignación múltiple. Para descartar uno de los los valores usan _:

Go
_, r := divmod(17, 5) // solo il resto

El patrón (T, error) canónico

Casi todo el stdlib lo sigue. error SIEMPRE es el último:

Go
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"):

Go
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:

Go
type Result struct {
    Sum  int
    Avg  float64
    Max  int
}

func analyze(nums []int) (Result, error) { ... }

Pruébalo

Ejercicio#go.m3.l2.e1
Intentos: 0Cargando...

Defina divmod(a, b int) (int, int) que devuelva el cociente y el resto.

Cargando editor...
Mostrar pista

Tipos de retorno entre paréntesis: `(int, int)`.

Solución disponible después de 3 intentos

Ejercicio#go.m3.l2.e2
Intentos: 0Cargando...

Implementar safeDiv(a, b int) (int, error): si b == 0 devuelve (0, errores.New('división por cero')), en caso contrario (a/b, nil).

Cargando editor...
Mostrar pista

Error SIEMPRE como último valor. En caso de error: valor cero + error.

Solución disponible después de 3 intentos

Cuestionario#go.m3.l2.e3
Listo

¿Qué imprime este programa utilizando devoluciones con nombre?

Go
func f() (a, b int) {
    a = 1
    b = 2
    return
}
x, y := f()
fmt.Println(x, y)
Opciones de respuesta

Resumen

  • Múltiples valores entre paréntesis: func f() (T1, T2, error).
  • Convención: error SIEMPRE 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.