go scope lexical-scope shadowing

¿Dónde podemos usar el alcance variable y el sombreado en Go?



scope lexical-scope (1)

Algunos mensajes relacionados que he encontrado:

También hay muchos casos de uso para el alcance variable y el sombreado.
Cualquier código de muestras o respuestas será apreciado.


Alcance variable y sombreado

Go tiene un alcance léxico usando bloques:

1-El alcance de un identificador predefinido es el bloque del universo.
2-El alcance de un identificador que denota una constante, tipo, variable o función (pero no método) declarado en el nivel superior (fuera de cualquier función) es el bloque del paquete.
3-El alcance del nombre del paquete de un paquete importado es el bloque de archivo del archivo que contiene la declaración de importación.
4-El alcance de un identificador que denota un receptor de método, un parámetro de función o una variable de resultado es el cuerpo de la función.
5-El alcance de un identificador de constante o variable declarado dentro de una función comienza al final de ConstSpec o VarSpec (ShortVarDecl para declaraciones de variables cortas) y termina al final del bloque que lo contiene más interno.
6-El alcance de un identificador de tipo declarado dentro de una función comienza en el identificador en TypeSpec y termina al final del bloque que lo contiene más interno.
Un identificador declarado en un bloque puede ser redeclarado en un bloque interno.
Mientras que el identificador de la declaración interna está en el alcance, denota la entidad declarada por la declaración interna.

La cláusula del paquete no es una declaración; el nombre del paquete no aparece en ningún ámbito. Su objetivo es identificar los archivos que pertenecen al mismo paquete y especificar el nombre del paquete predeterminado para las declaraciones de importación.

Ventajas:

  • Dado que no se puede acceder a los datos desde el ámbito externo, se preserva la integridad de los datos

Diferentes formas de sombreado variable en Go:

1- Forma de Golang para limitar el alcance de la variable (usando la asignación de mano corta dentro de las declaraciones):

package main import "fmt" func main() { i := 10 //scope: main j := 4 for i := ''a''; i < ''b''; i++ { // i shadowed inside this block fmt.Println(i, j) //97 4 } fmt.Println(i, j) //10 4 if i := "test"; len(i) == j { // i shadowed inside this block fmt.Println(i, j) // i= test , j= 4 } else { // i shadowed inside this block fmt.Println(i, j) //test 40 } fmt.Println(i, j) //10 4 }

2- Cuando "necesitamos más alfabetos", esta es una buena manera de limitar el alcance de las variables .
También esto funciona bien cuando necesita más variables locales o alcance:

usando { y } par:
Pros: no hay necesidad de declaraciones adicionales como si, por, ...

package main import "fmt" func main() { i := 1 j := 2 //new scope : { i := "hi" //new local var j++ fmt.Println(i, j) //hi 3 } fmt.Println(i, j) //1 3 }

3- Otra forma de limitar el alcance variable es usar llamadas a funciones :
Pros: el límite de alcance, los parámetros de tipo de valor de entrada se pueden usar como variables locales,
Contras: tiempo de llamada / retorno y uso de la pila: si no está optimizado por el compilador

package main import "fmt" func fun(i int, j *int) { i++ //+nice: use as local var without side effect *j++ //+nice: intentionally use as global var fmt.Println(i, *j) //11 21 } func main() { i := 10 //scope: main j := 20 fun(i, &j) fmt.Println(i, j) //10 21 }

4- Otra forma es sombreando las variables globales :

package main import "fmt" var i int = 1 //global func main() { j := 2 fmt.Println(i, j) //1 2 i := 10 //Shadowing global var fmt.Println(i, j) //10 2 fun(i, j) //10 2 } func fun(i, j int) { //i := 100 //error: no new variables on left side of := //var i int = 100 //error: i redeclared in this block fmt.Println(i, j) //10 2 }

Ver: sombreado variable y alcance .
Y: Declaraciones y alcance :