09. Go to go: funciones y ámbitos

Publicado por

A veces necesitamos que algunos de nuestros algoritmos se ejecuten varias veces a lo largo de nuestro código, pero resultaría poco práctico copiarlos y pegarlos una y otra vez. Los ciclos podrían parecer una buena alternativa, sin embargo, ¿qué pasaría si esas repeticiones están dispersas a lo largo del código? Para ese tipo de situaciones podemos recurrir a las funciones.

Una función o subrutina es una sección de código que realiza una tarea en específico. Todos los programas cuentan con, al menos, una función main (principal) con la posibilidad de definir más funciones para realizar subtareas. Todas las funciones se diferencian entre ellas, y de las variables, por medio de un identificador único.

La sintaxis de la declaración de funciones en Golang es la siguiente:

Declaración_funciones = "func" Nombre_función ( Función | Firma )
Nombre_función = identificador
Función = Firma Cuerpo_función
Firma = Parámetros [Resultado]
Parámetros = "(" [ Lista_parámetros [ "," ] ] ")"
Resultado = Parámetros | Tipo
Tipos = Nombre_tipo | Literal_tipo | "(" Tipo ")"
Cuerpo_funcion = Bloque
Bloque = "{" Lista_declaraciones "}"

En base a lo anterior, podemos identificar:

  • func es la palabra reservada que inicia la declaración de una función.
  • Firma es la lista de parámetros.
  • Nombre_función es el identificador de nuestra función.
  • Parámetros son los valores que se pasan a una función para trabajar dentro de ella. Puede haber cualquier cantidad de parámetros, o ninguno.
  • Tipo es la lista de resultados que devuelve una función por medio de un return. Puede haber cualquier cantidad de resultados, o ninguno. El número de ellos debe coincidir con los devueltos por la sentencia return en cantidad y tipo.
  • Cuerpo_función contiene las instrucciones de la función. Si se especificó un resultado, en esta sección debe de colocarse un return con los correspondientes datos a regresar.

Más información sobre sintaxis aquí y aquí.

Ejemplo de función:

La siguiente función se llama mult, recibe dos parámetros enteros (numero1 y numero2), su tarea es multiplicar esos números que recibió y devolver el producto:

func mult(numero1, numero2 int) int{

  /*Variable local de la función*/

  var resultado int

  resultado = numero1 * numero2

  return resultado

}

Llamado a una función

La función del ejemplo anterior teóricamente multiplicaba dos números, sin embargo, si no se le hace un llamado, solamente será código sin uso. Si se llama a una función, el control del programa se transfiere a esta última hasta que se alcanza una sentencia return, o hasta que se terminan las instrucciones dentro de la sección del cuerpo.

Para hacer un llamado a función, se utiliza el identificador de la función (nombre) y se pasan los parámetros necesarios. Si la función regresa algún valor, este puede ser almacenado en variables.

Ejemplo:

package main
import “fmt”

func main(){
  /*Variable local*/
  var res int

  /*Llamado a función*/
  fmt.Printf("El resultado de 122*120: %d\n", mult(122, 120))

  /*Llamado con parámetros distintos*/
  fmt.Printf("El resultado de 130*105: %d\n", mult(130, 105))

  /*Se almacena el resultado en una variable*/
  res = mult(20, 178)
  fmt.Printf("Resultado almacenado en una variable: %d\n", res)
}

/*Función que multiplica dos números*/
func mult(numero1, numero2 int) int{
  /*Variable local de la función*/
  var resultado int

  resultado = numero1 * numero2

  return resultado
}

Funciones que regresan más de un valor

A diferencia de otros lenguajes de programación, las funciones en Golang puede regresar más de un valor con un return. El siguiente ejemplo muestra una función que regresa dos valores, sin embargo, cabe aclarar que puede ser devuelta cualquier cantidad de valores de cualquier tipo:

package main
import "fmt"

func main(){
   /*Llamado a la función*/
  min, max := minmax(12, 23, 54)

  fmt.Printf("Min: %d\nMax: %d\n", min, max)
}

/*Función para encontrar el MÍNIMO
y MÁXIMO entre tres números*/
func minmax(a, b, c int) (int, int){
  /*Variables locales*/
  var min, max int

  /*Se encuentra el MÁXIMO, luego el MÍNIMO*/
  /*Primero verifica si "a" es el MÁXIMO*/
  if a > b && a > c{
    max = a

    if b < c{
      min = b
    }else{
      min = c
    }

  /*Si "a" no fue el MÁXIMO, prueba con "b"*/
  }else if b > a && b > c{
    max = b

    if a < c{
      min = a
    }else{
      min = c
    }

  /*Si "a" y "b" no fueron los MÁXIMOS, prueba con "c" */
  }else{
    max = c

    if a < b{
      min = a
    }else{
      min = b
    }
  }

  return min, max

}

Ámbito de una variable

Nótese que en las funciones de los ejemplos anteriores se utilizó un concepto nuevo: variables locales. Una variable local es aquella a la que solamente se puede acceder desde ciertas partes de nuestros programas. Regularmente a esta característica de los lenguajes de programación se le conoce como ámbito.

El ámbito se refiere a una región del programa en la que una variable existe. En la siguiente imagen se utilizaron colores diferentes para diferenciar ámbitos distintos:

ámbito-golang
Ámbito de variables (Go)
  • Las variables del ámbito verde pueden ser consultadas por los ámbitos rojo y amarillo.
  • Las variables del ámbito rojo y amarillo no pueden ser consultadas por el ámbito verde.
  • Las variables del ámbito rojo se pueden acceder desde el ámbito amarillo.
  • Las variables del ámbito amarillo no se pueden acceder desde el ámbito rojo.
  • Las variables del ámbito cian no pueden consultarse desde ningún otro ámbito y viceversa.
  • Los número 1 y 2 marcan dos sentencias erróneas que intentan acceder a variables de un ámbito al que no pueden hacerlo.
  • En el ámbito amarillo se utiliza la variable i que pertenece al ámbito rojo.

Las variables pueden ser declaradas en 3 lugares distintos:

  1. Dentro de una función o bloque de código. En este caso las variables son conocidas como locales, y solamente se puede acceder a ellas dentro del ámbito al que pertenecen y desde otros internos a él.
  2. Fuera de todas las funciones. En este caso se les conoce como variables globales y se puede acceder a ellas desde cualquier parte del programa.
  3. En la definición de una función. Se les conoce como parámetros formales y solamente se puede acceder a ellas desde la función en la que se declaran.

Haciendo unos pequeños cambios a los ejemplos anteriores, podemos observar los ámbitos en acción:

package main
import "fmt"

/*Variable global*/
var resglobal int

/*Función principal*/
func main(){
  /*Variable local de main*/
  var resultado int

  /*Modificando una variable global desde main*/
  resglobal = 31

  resultado = mult(20, 178)
  fmt.Printf("Resultado de multiplicación: %d\n", resultado)

}

/*numero1 y numero2 son parámetros formales
y su ámbito es local a la función mult*/
func mult(numero1, numero2 int) int{
  /*Variable local de la función mult con el
  mismo nombre que una variable local de main*/
  var resultado int

  resultado = numero1 * numero2

  /*Accediendo a variable global desde función*/
  fmt.Printf("Valor en variable global: %d\n", resglobal)

  return resultado

}

Finalizando…

Las funciones son una herramienta poderosa para mejorar nuestros programas, y en esta nota estudiamos lo necesario para comenzar a realizar pruebas de su funcionamiento. En la próxima entrada será tiempo de aprender un concepto nuevo que nos brindará otra alternativa para trabajar con funciones: los apuntadores. Nos vemos, hasta la próxima.

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *