问题
Some related posts I've found:
- go variable scope and shadowing
- Golang: variable scope inside if statements
- Limit the scope of variables storing error
Also there are many use cases to Variable Scoping and Shadowing.
Any code samples or answers will be appreciated.
回答1:
Variable scoping and shadowing:
Go is lexically scoped using blocks:
- The scope of a predeclared identifier is the universe block.
- The scope of an identifier denoting a constant, type, variable, or function (but not method) declared at top level (outside any function) is the package block.
- The scope of the package name of an imported package is the file block of the file containing the import declaration.
- The scope of an identifier denoting a method receiver, function parameter, or result variable is the function body.
- The scope of a constant or variable identifier declared inside a function begins at the end of the ConstSpec or VarSpec (ShortVarDecl for short variable declarations) and ends at the end of the innermost containing block.
- The scope of a type identifier declared inside a function begins at the identifier in the TypeSpec and ends at the end of the innermost containing block.
An identifier declared in a block may be redeclared in an inner block.
While the identifier of the inner declaration is in scope, it denotes the entity declared by the inner declaration.The package clause is not a declaration; the package name does not appear in any scope. Its purpose is to identify the files belonging to the same package and to specify the default package name for import declarations.
Advantages:
- Since data cannot be accessed from outer scope, Data Integrity is preserved
Different forms of Variable shadowing in Go:
Golang way to limit variable scope (using short-hand assignment inside statements):
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 }
When "we need more alphabets", this is nice way to limit variables scope.
Also this works well when you need more local variables or scope:using
{
and}
pair:
Pros: no need to extra statements like if, for, …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 }
Another way to limit variable scope is using function calls:
Pros: scope limit, input value type parameters are usable like local variables,
Cons: call/return time, and stack usage: if it is not optimized by compilerpackage 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 }
Another way is shadowing global variables:
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 }
See: Variable shadowing and Scope.
And: Declarations and scope:
来源:https://stackoverflow.com/questions/36553134/where-can-we-use-variable-scoping-and-shadowing-in-go