我发现的一些相关帖子:
还有很多用于变量范围和阴影的用例 任何代码示例或答案将不胜感激。
答案 0 :(得分:5)
变量范围和阴影:
Go使用块进行词法作用:
- 预先声明的标识符的范围是Universe块。
- 标识符的范围,表示常量,类型,变量或 在顶层声明的函数(但不是方法)(在任何函数之外) 是包块。
- 导入的包名称的范围 package是包含导入的文件的文件块 宣言。
- 表示方法的标识符的范围 接收器,函数参数或结果变量是函数体。
- 在a中声明的常量或变量标识符的范围 函数从ConstSpec或VarSpec(ShortVarDecl 对于短变量声明)并在最里面的末尾结束 包含块。
- 在a中声明的类型标识符的范围 function从TypeSpec中的标识符开始,到结尾处结束 最里面的包含块 块中声明的标识符可以在内部块中重新声明。
醇>
虽然内部声明的标识符在范围内,但它 表示内部声明声明的实体。包条款不是声明;包名称没有 出现在任何范围内。其目的是识别属于的文件 相同的包并指定导入的默认包名称 声明。
Golang限制变量范围的方法(在语句中使用短手赋值):
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
}
当“我们需要更多字母”时,这是限制变量范围的好方法。
当您需要更多局部变量或范围时,这也很有效:
使用{
和}
对:
优点:不需要额外的陈述,如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
}
限制变量范围的另一种方法是使用函数调用:
优点:范围限制,输入值类型参数可用于局部变量,
缺点:调用/返回时间和堆栈使用:如果它没有被编译器优化
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
}
另一种方法是遮蔽全局变量:
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
}