jueves, 25 de octubre de 2018

Visibilidad de datos y funciones en Go

Uno de los aspectos más importantes en Go es conocer la visibilidad de las variables y constantes, así como también de los métodos que utilizamos en nuestros programas.


Regla de oro: visibilidad en bloques de código

En Go, al igual que en otros lenguajes de programación, el código se organiza en bloques. Estos bloques están comprendidos entre llaves ({ ... }). Un ejemplo de bloque de código sería una función (o método), o un bucle for o un bloque condicional if.

La regla de oro es esta: una variable definida en un bloque de código, sólo es visible dentro de este bloque.

Niveles jerárquicos en bloques de código

Dentro de un bloque de código se pueden definir nuevos bloques (y, dentro de estos, sucesivamente, nuevos bloques), formando una jerarquía de niveles o un anidamiento de bloques de código. Por ejemplo, dentro de una función (o método) puede definirse un bloque if, y, dentro de este if se puede definir un nuevo bloque if o un bloque de bucle for.

Una variable o constante tiene visibilidad dentro del bloque en que se define, y en todos los bloques dentro de este bloque, es decir, en las jerarquías de nivel más internas o profundas. Si una variable se define en un bloque más interno, ésta no se podrá ver o acceder en bloques de nivel superior.

El código muestra un ejemplo muy sencillo de visibilidad por niveles de bloques de código:

func main() {
   // numero se ve solo dentro de la funcion main()
   var numero int = 123

   fmt.Println("main() > numero: ", numero)

   if numero == 123 {
      // otroNumero solo se ve dentro del if
      var otroNumero int = 987

      fmt.Println("main() > if > numero: ", numero)
      fmt.Println("main() > if > otroNumero: ", otroNumero)
   }
}

A la regla de oro se le añadiría la coletilla: una variable definida en un bloque de código, sólo es visible dentro de este bloque y en los bloques de nivel inferior.

Visibilidad de los parámetros de una función

Las funciones (o métodos) pueden recibir parámetros de entrada. Estos parámetros serían las primeras variables que se definen (de forma implícita) en la función, por lo que tienen una visibilidad en todo el bloque de código de la función.

func funcion(param string) {

   var numero int = 123

   fmt.Println("funcion() > param: ", param)
   fmt.Println("funcion() > numero: ", numero)

   if numero == 123 {
      var otroNumero int = 987

      fmt.Println("funcion() > if > param: ", param)
      fmt.Println("funcion() > if > numero: ", numero)
      fmt.Println("funcion() > if > otroNumero: ", otroNumero)
   }

}

Nota: ¿Qué diferencia hay entre un método y una función? Básicamente es lo mismo, pero la principal diferencia es que un método no devuelve nada, mientras que una función puede retornar valores. Para Go, todo es una función (de hecho, utiliza la palabra reservada func para definir tanto una función como un método).

Visibilidad en un archivo de código Go

El archivo de código Go sería el nivel superior del código que aloja. Dentro de este archivo definimos las diferentes funciones que conformarán nuestro programa, como la función main(). Estas funciones se definen en un primer nivel, y son visibles dentro del propio archivo, por lo que una de estas funciones puede llamar a otra función del mismo archivo, pues pertenecen al mismo nivel.

Podemos definir también variables a nivel de archivo, por lo que serían visibles en todas las funciones de dicho archivo.

Ejemplo

El siguiente ejemplo ilustra todos los concepto vistos anteriormente:

package main

import "fmt"

var curso string = "Go"

func main() {
   fmt.Println("main() > curso: ", curso)
   funcion("XYZ")
}

// El parametro 'param' solo es visible
// dentro del metodo miMetodo
func funcion(param string) {

   // Variable local al metodo
   // Solo se ve en miMetodo
   var numero int = 123

   fmt.Println("funcion() > curso: ", curso)
   fmt.Println("funcion() > param: ", param)
   fmt.Println("funcion() > numero: ", numero)

   if numero == 123 {
      // Variable local al if
      // Solo se ve dentro del if
      var otroNumero int = 987
      fmt.Println("funcion() > if > curso: ", curso)
      fmt.Println("funcion() > if > param: ", param)
      fmt.Println("funcion() > if > numero: ", numero)
      fmt.Println("funcion() > if > otroNumero: ", otroNumero)
   }

}

El resultado será el siguiente:

$ run go visibilidad-archivo.go
main() > curso:  Go
funcion() > curso:  Go
funcion() > param:  XYZ
funcion() > numero:  123
funcion() > if > curso:  Go
funcion() > if > param:  XYZ
funcion() > if > numero:  123
funcion() > if > otroNumero:  987

No hay comentarios:

Publicar un comentario