18 - Definición de funciones en Go

Hasta ahora hemos trabajado resolviendo todo el algoritmo en la función main. Todas las instrucciones de nuestro programa se ejecutan en forma secuencial de principio a fin.

Esta forma de organizar un programa solo puede ser utilizado si el mismo es muy pequeño (decenas de líneas)

Cuando los problemas a resolver tienden a ser más grandes la metodología de programación lineal se vuelve ineficiente y compleja.

Ahora vamos a dividir o descomponer un problema complejo en pequeños problemas. La solución de cada uno de esos pequeños problemas nos trae la solución del problema complejo.

En el lenguaje Go el planteo de esas pequeñas soluciones al problema complejo se hace dividiendo el programa en funciones.

Una función es un conjunto de instrucciones en Go que resuelven un problema específico. En el lenguaje Go es obligatorio el planteo de una función como mínimo llamada main:

func main() {
    ....
}

El lenguaje Go tiene una serie de paquetes que proveen algunas funcionalidades básicas. Hasta ahora hemos empleado las funciones que nos provee el paquete "fmt".

Veamos ahora como crear nuestras propias funciones.

El tema de funciones en un principio puede presentar dificultades para entenderlo y ver sus ventajas ante la metodología de programación lineal que veníamos trabajando todo en la función main.

Los primeros problemas que presentaremos nos puede parecer que sea más conveniente trabajar todo en la función main en vez de dividir el problema en varias funciones.

A medida que avancemos veremos que si un programa empieza a ser más complejo (cientos de líneas, miles de líneas o más) la división en pequeñas funciones nos permitirá tener un programa más ordenado y fácil de entender y por lo tanto en mantener.

Estructura de una función.

Una función comienza con la palabra clave func y seguida a esta su nombre, puede tener parámetros, un valor o más de retorno y encerrada entre llaves le sigue su algoritmo (la llave de apertura debe ir en la mísma línea de la definición de la función):

func [nombre de la función] ([parámetros de la función]) [valor/es que retorna] {
    [altoritmo]
}

Problema 1:

Confeccionar un programa que muestre una presentación en pantalla del programa. Solicite la carga de dos valores y nos muestre la suma. Mostrar finalmente un mensaje de despedida del programa.

Implementar estas actividades en tres funciones.

Programa: ejercicio085.go

package main

import "fmt"


func presentacion() {
    fmt.Println("Programa que permite cargar dos valores por teclado.")
    fmt.Println("Efectua la suma de los valores")
    fmt.Println("Muestra el resultado de la suma")
    fmt.Println("*******************************")
}

func cargaSuma() {
    var valor1,valor2 int
    fmt.Print("Ingrese el primer valor:")
    fmt.Scan(&valor1)
    fmt.Print("Ingrese el segundo valor:")
    fmt.Scan(&valor2)
    suma := valor1 + valor2
    fmt.Println("La suma de los dos valores es:", suma)
}

func finalizacion() {
    fmt.Println("*******************************")
    fmt.Println("Gracias por utilizar este programa")
}

func main() {
    presentacion()
    cargaSuma()
    finalizacion()
}

Como podemos observar hemos dispuesto previo a la función main otras tres funciones.

Lo importante es tener en cuenta que todo programa en Go comienza a ejecutarse siempre a partir de la primer línea contenida en la función main, en nuestro ejemplo sería:

func main() {
    presentacion()

Lo que estamos indicando en esta línea es llamar a la función presentacion (la función puede estar codificada en forma previa a la función main como es nuestro caso o no hay problemas si se encuentra codificada después de la función main)

La codificación de la función presentacion es:

func presentacion() {
    fmt.Println("Programa que permite cargar dos valores por teclado.")
    fmt.Println("Efectua la suma de los valores")
    fmt.Println("Muestra el resultado de la suma")
    fmt.Println("*******************************")
}

Veamos un poco la sintaxis necesaria para crear una función en el lenguaje Go.
Toda función comienza por la palabra clave func (recordemos que toda palabra clave en Go debe escribirse en minúsculas sino se mostrará un error sintáctico cuando compilemos el programa) y en forma seguida tiene un nombre que no puede tener espacios en blanco, comenzar con un número ni tener caracteres especiales.

Luego del nombre de la función indicamos entre paréntesis los parámetros, si no los tiene disponemos los paréntesis abiertos y cerrados, finalizamos con la apertura de la llave:

func presentacion() {

Luego del nombre de la función debe ir encerrado entre llaves el algoritmo propio de la función, en nuestro ejemplo disponemos una serie de llamadas a la función Println para mostrar la presentación del programa:

func presentacion() {
    fmt.Println("Programa que permite cargar dos valores por teclado.")
    fmt.Println("Efectua la suma de los valores")
    fmt.Println("Muestra el resultado de la suma")
    fmt.Println("*******************************")
}

Cuando se ejecuta esta función al llegar a la llave de cerrado vuelve a la función main desde donde se la llamó.

De regreso en la función main ahora se llama a la función cargaSuma:

func main() {
    presentacion()
    cargaSuma()

El programa ahora nuevamente sale de la función main y pasa a ejecutarse la función cargaSuma:

func cargaSuma() {
    var valor1,valor2 int
    fmt.Print("Ingrese el primer valor:")
    fmt.Scan(&valor1)
    fmt.Print("Ingrese el segundo valor:")
    fmt.Scan(&valor2)
    suma := valor1 + valor2
    fmt.Println("La suma de los dos valores es:", suma)
}

La función cargaSuma no tiene parámetros

Dentro del algoritmo de la función cargaSuma definimos tres variables llamadas locales a la función cargaSuma. Estas variables solo existen mientras se ejecuta la función cargaSuma y no pueden ser utilizadas por las otras funciones de nuestro programa.

El algoritmo de cargar dos valores por teclado, sumarlos y mostrar la suma por pantalla no varía con lo visto anteriormente, pero si varía la ubicación de dicho algoritmo dentro de una función creada por nosotros.

Cuando finaliza de ejecutarse cada una de las instrucciones de la función cargaSuma regresa a la función main donde se procederá a llamar a la tercer función que creamos nosotros llamada finalizacion:

func main() {
    presentacion()
    cargaSuma()
    finalizacion()

Como vemos desde la main debemos indicar el nombre exacto de la función que llamamos (recordar que el lenguaje Go es sensible a mayúsculas y minúsculas)

La función finalizacion tiene por objetivo mostrar una serie de mensajes por pantalla para que el operador sepa que el programa está finalizando:

func finalizacion() {
    fmt.Println("*******************************")
    fmt.Println("Gracias por utilizar este programa")
}

Luego de ejecutar los dos Println de la función finalizacion el programa regresa a la main:

func main() {
    presentacion()
    cargaSuma()
    finalizacion()
}

En la main no hay más instrucciones con lo que el programa finaliza.

Si ejecutamos el programa podemos ver una salida por pantalla similar a esta:

funciones en go

Recordar que cuando se llama a una función desde la main cuando la misma finaliza regresa a la siguiente línea de la main:

funciones en go

Si no hacemos las llamadas a las funciones los algoritmos que implementan las funciones previas a la main nunca se ejecutarán:

func main() {
}

El orden que llamamos a las funciones desde la main también es muy importante, si implementamos la main con este orden de llamadas a las funciones el resultado será muy distinto:

func main() {
    finalizacion()
    cargaSuma()
    presentacion()
}

Problema 2:

Confeccionar una aplicación que solicite la carga de dos valores enteros y muestre su suma.
Repetir la carga de otros dos valores, sumarlos y mostrar.
Mostrar una línea separadora después de cada vez que cargamos dos valores y mostramos su suma.

Programa: ejercicio086.go

package main

import "fmt"


func cargaSuma() {
    var valor1, valor2 int
    fmt.Print("Ingrese el primer valor:")
    fmt.Scan(&valor1)
    fmt.Print("Ingrese el segundo valor:")
    fmt.Scan(&valor2)
    suma := valor1 + valor2
    fmt.Println("La suma de los dos valores es:", suma)
}

func separacion() {
    fmt.Println()
    fmt.Println("*******************************")
    fmt.Println()    
}

func main() {
    cargaSuma()
    separacion()
    cargaSuma()
    separacion()
}

Hemos declarado dos funciones, una que permite cargar dos enteros sumarlos y mostrar el resultado:

func cargaSuma() {
    var valor1, valor2 int
    fmt.Print("Ingrese el primer valor:")
    fmt.Scan(&valor1)
    fmt.Print("Ingrese el segundo valor:")
    fmt.Scan(&valor2)
    suma := valor1 + valor2
    fmt.Println("La suma de los dos valores es:", suma)
}

Y otra función que tiene por objetivo mostrar una línea separadora con asteriscos:

func separacion() {
    fmt.Println()
    fmt.Println("*******************************")
    fmt.Println()    
}

Ahora en nuestra función main, recordemos que estas líneas son las primeras que se ejecutarán cuando se inicie el programa:

func main() {
    cargaSuma()
    separacion()
    cargaSuma()
    separacion()
}

Como vemos podemos llamar a la función cargaSuma() varias veces, esta es una ventaja con respecto a desarrollar todo en la main.

Lo nuevo que debe quedar claro es que la llamada a las funciones desde la función main de nuestro programa puede hacerse múltiples veces (esto es lógico, recordemos que Print es una función existente en el paquete "fmt" y la llamamos múltiples veces dentro de nuestro algoritmo)

Problemas propuestos

  • Desarrollar un programa con dos funciones aparte de la main. La primer solicite el ingreso de un entero y muestre el cuadrado de dicho valor. La segunda que solicite la carga de dos valores y muestre el producto de los mismos.
    Llamar desde la main a ambas funciones.
  • Desarrollar una función que solicite la carga de tres valores y muestre el menor. Desde la función main llamar 3 veces a dicha función.
Solución
ejercicio087.go

package main

import "fmt"

func calcularCuadrado() {
    var valor int
    fmt.Print("Ingrese un entero:")
    fmt.Scan(&valor)
    cuadrado := valor * valor
    fmt.Println("El cuadrado es ", cuadrado)
}

func calcularProducto() {
    var valor1, valor2 int
    fmt.Print("Ingrese primer valor:")
    fmt.Scan(&valor1)
    fmt.Print("Ingese segundo valor:")
    fmt.Scan(&valor2)
    producto := valor1 * valor2
    fmt.Println("El producto de los valores es:", producto)
}

func main() {
    calcularCuadrado()
    calcularProducto()
}




ejercicio088.go

package main

import "fmt"


func menorValor() {
    var valor1, valor2, valor3 int
    fmt.Print("Ingrese primer valor:")
    fmt.Scan(&valor1)
    fmt.Print("Ingrese segundo valor:")
    fmt.Scan(&valor2)
    fmt.Print("Ingrese tercer valor:")
    fmt.Scan(&valor3)
    if valor1 < valor2 && valor1 < valor3 {
        fmt.Println("Menor valor:", valor1)
    } else {
        if valor2 < valor3 {
            fmt.Println("Menor valor:", valor2)
        } else {
            fmt.Println("Menor valor:", valor3)
        }
    }
}


func main() {
    menorValor()
    menorValor()
    menorValor()
}