21 - Funciones: con retorno de varios valores

Hemos visto que una función puede retornar un valor. En este concepto veremos que una función en Go puede retornar más de un valor y luego ser recuperados desde donde llamamos a la función.

Problema 1:

Confeccionar una función que le enviemos dos enteros y nos retorne el mayor y menor en ese orden. En la main solicitar la carga de dos valores por teclado y llamar a la función.

Programa: ejercicio101.go

package main

import "fmt"

func mayorMenor(v1, v2 int) (int, int) {
    if v1 > v2 {
        return v1, v2
    } else {
        return v2, v1
    }
}

func main() {
    var x1, x2 int
    fmt.Print("Ingrese primer valor:")
    fmt.Scan(&x1)
    fmt.Print("Ingrese segundo valor:")
    fmt.Scan(&x2)
    var may, men int
    may, men = mayorMenor(x1, x2)
    fmt.Println("El mayor es:", may)
    fmt.Println("El menor es:", men)
}

La función mayorMenor recibe como parámetros dos enteros y luego indicamos entre paréntesis los tipos de datos que retorna (en este caso retorna 2 enteros):

func mayorMenor(v1, v2 int) (int, int) {

Como la función retorna dos enteros debemos indicar en el comando return los valores a devolver:

    if v1 > v2 {
        return v1, v2
    } else {
        return v2, v1
    }

La llamada a la función se hace disponiendo del lado izquierdo del operador = dos variables enteras que almacenarán los valores retornados por la función mayorMenor:

    var may, men int
    may, men = mayorMenor(x1, x2)

En la variable may se almacena el primer valor indicado en el return y en men se almacena el segundo valor indicado en el comando return.

El lenguaje Go nos permite definir dos variable por inferencia con los valores devueltos por la función mayor sin tener que definir en forma explícita las dos variables (nos ahorramos la definición de may y men):

    may, men := mayorMenor(x1, x2)

Problema 2:

Confeccionar una función que le enviemos un array de 5 enteros y nos retorne el mayor y menor en ese orden. En la main definir y cargar un array.

Programa: ejercicio102.go

package main

import "fmt"

func mayorMenor(vec [5]int) (int, int) {
    var may = vec[0]
    var men = vec[0]
    for f := 1; f < len(vec); f++ {
        if vec[f] > may {
            may = vec[f]
        } else {
            if vec[f] < men {
                men = vec[f]
            }
        }
    }
    return may, men
}


func main() {
    vector := [5]int{12,2,30,1,5}
    may, men := mayorMenor(vector)
    fmt.Println("El elemento mayor del vector es:", may)
    fmt.Println("El elemento menor del vector es:", men)
}

Una función en Go puede recibir como parámetro un vector (el parámetro recibe una copia del vector que le enviamos en este caso de la main), además en este problema retorna dos enteros que son el mayor y menor del vector:

func mayorMenor(vec [5]int) (int, int) {

El algoritmo para obtener el mayor y menor del vector array consiste en definir dos variables locales con la primer componente del vector suponiendo que se trata del menor y mayor elemento del vector:

    var may = vec[0]
    var men = vec[0]

Luego analizamos los cuatro elementos que nos quedan del vector para ver si hay alguno elementos mayor o menor del que hemos considerado hasta ahora:

    for f := 1; f < len(vec); f++ {
        if vec[f] > may {
            may = vec[f]
        } else {
            if vec[f] < men {
                men = vec[f]
            }
        }
    }

Cuando finaliza la estructura repetitiva podemos retornar el mayor y menor mediante la palabra clave return:

    return may, men

En la función main definimos un vector de 5 elementos enteros y lo inicializamos:

    vector := [5]int{12,2,30,1,5}

Finalmente llamamos a la función mayorMenor enviando el vector y esperando que nos retorne dos enteros que serán almacenados en las variables may y men:

    may, men := mayorMenor(vector)
    fmt.Println("El elemento mayor del vector es:", may)
    fmt.Println("El elemento menor del vector es:", men)
}

Descartar valores devueltos por una función.

Hemos visto que cuando una función retorna más de un valor disponemos del lado izquierdo las variables que reciben los datos. En algunas situaciones si no necesitamos alguno de los valores devueltos podemos utilizar el identificador vacío (se lo indica con el caracter de subrayado _) para descartar el valor retornado.

Si en el ejemplo 2 solo queremos recuperar el valor mayor del vector y descartar el menor la sintaxis en la main será:

func main() {
    vector := [5]int{12,2,30,1,5}
    may, _ := mayorMenor(vector)
    fmt.Println("El elemento mayor del vector es:", may)

}

Veremos que es común que muchas funciones en Go retornen varios valores y que descartemos alguno de ellos utilizando el identificador vacío.

Resultados nombrados.

Podemos utilizar una sintaxis alternativa para la devolución de varios valores por parte de una función, esta técnica en Go se la llama resultados nombrados.

La técnica consiste en indicar un nombre a cada valor devuelto. Dentro del algoritmo de la función asignamos valores (problema 1):

Programa: ejercicio103.go

package main

import "fmt"

func mayorMenor(v1, v2 int) (may int, men int) {
    if v1 > v2 {
        may = v1
        men = v2
    } else {
        may = v2
        men = v1
    }
    return
}

func main() {
    var x1, x2 int
    fmt.Print("Ingrese primer valor:")
    fmt.Scan(&x1)
    fmt.Print("Ingrese segundo valor:")
    fmt.Scan(&x2)
    var may, men int
    may, men = mayorMenor(x1, x2)
    fmt.Println("El mayor es:", may)
    fmt.Println("El menor es:", men)
}

Especificamos nombres a los dos datos que devuelve la función (may y men):

func mayorMenor(v1, v2 int) (may int, men int) {

Dentro del algoritmo cargamos los datos a devolver:

    if v1 > v2 {
        may = v1
        men = v2
    } else {
        may = v2
        men = v1
    }

Por último disponemos la palabra clave return para finalizar la función (es obligatorio y no debemos indicar ningún valor):

    return

Problemas propuestos

  • Confeccionar una función que solicite la carga de valores enteros por teclado (se finaliza al ingresar el cero)
    La función retorna la cantidad de valores positivos y negativos ingresados.
  • Confeccionar una función que recibe un vector de 10 elementos enteros positivos, retornar la cantidad de elementos con 1 dígito, 2 dígitos y más de dos dígitos.
Solución
ejercicio104.go

package main

import "fmt"

func positivosNegativos() (int, int) {
    var valor int
    positivos := 0
    negativos := 0
    for {        
        fmt.Print("Ingrese un valor (0 para finalizar):")
        fmt.Scan(&valor)
        if valor == 0 {
            break
        } else {
            if valor > 0 {
                positivos++
            } else {
                negativos++
            }
        }
    }
    return positivos, negativos
}


func main() {
    positivos, negativos := positivosNegativos()
    fmt.Println("La cantidad de valores positivos ingresados son:", positivos)
    fmt.Println("La cantidad de valores negativos ingresados son:", negativos)
}




ejercicio105.go

package main

import "fmt"

func unoDosMasDigitos(vec [10]int) (int, int, int) {
    uno := 0
    dos := 0
    mas := 0
    for f := 0; f< len(vec); f++ {
        if vec[f] < 10 {
            uno++
        } else {
            if vec[f] <100 {
                dos++
            } else {
                mas++
            }
        }
    }
    return uno, dos, mas
}


func main() {
    vector := [10]int{100, 200, 34, 6, 200, 90, 12, 245, 85, 23}
    v1, v2, v3 := unoDosMasDigitos(vector)
    fmt.Println("Cantidad de elementos con 1 dígito:", v1)
    fmt.Println("Cantidad de elementos con 2 dígitos:", v2)
    fmt.Println("Cantidad de elementos con más de 2 dígitos:", v3)
}