我们在哪里可以使用Go中的变量范围和阴影?

1 scope go shadowing lexical-scope

我找到的一些相关帖子:

还有许多用于变量范围和阴影的用例.
任何代码示例或答案将不胜感激.

小智 5

变量范围和阴影:

Go是使用块的词法范围:

  1. 预先声明的标识符的范围是Universe块.
  2. 表示在顶层(在任何函数之外)声明的常量,类型,变量或函数(但不是方法)的标识符的范围是包块.
  3. 导入包的包名称范围是包含导入声明的文件的文件块.
  4. 表示方法接收者,函数参数或结果变量的标识符的范围是函数体.
  5. 在函数内声明的常量或变量标识符的范围从ConstSpec或VarSpec(短变量声明的ShortVarDecl)结束开始,并在最内层包含块的末尾结束.
  6. 在函数内声明的类型标识符的范围从TypeSpec中的标识符开始,并在最内层包含块的末尾结束.
    块中声明的标识符可以在内部块中重新声明.
    虽然内部声明的标识符在范围内,但它表示内部声明声明的实体.

包条款不是声明; 包名称不会出现在任何范围内.其目的是识别属于同一包的文件,并指定导入声明的默认包名.

好处:

  • 由于无法从外部范围访问数据,因此将保留数据完整性

Go中不同形式的变量阴影:

  1. 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
    }
    
    Run Code Online (Sandbox Code Playgroud)
  2. 当"我们需要更多字母"时,这是限制变量范围的好方法.
    当您需要更多局部变量或范围时,这也很有效:

    使用{和}配对:
    优点:不需要额外的陈述,如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
    }
    
    Run Code Online (Sandbox Code Playgroud)
  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
    }
    
    Run Code Online (Sandbox Code Playgroud)
  4. 另一种方法是遮蔽全局变量:

    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
    }
    
    Run Code Online (Sandbox Code Playgroud)

请参阅:变量阴影和范围.
并且:声明和范围: