我们可以在Go中使用变量范围和阴影吗? [英] Where can we use Variable Scoping and Shadowing in Go?

查看:138
本文介绍了我们可以在Go中使用变量范围和阴影吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我发现的一些相关帖子:



还有很多使用情况的变量范围和阴影。

任何代码示例或答案将不胜感激。

解决方案

变量范围和阴影:


Go使用块进行词汇范围:

b
$ b


  1. 预定义标识符的范围是Universe块。

  2. 在顶层(任何函数之外)
    声明的表示常量,类型,变量或
    函数(但不是方法)的标识符的范围是包块。

  3. 导入的
    包的包名的范围是包含导入
    声明的文件的文件块。

  4. 表示方法
    receiver,函数参数或结果变量的标识符范围是函数体。

    函数中声明的常量或变量标识符的范围从ConstSpec或VarSpec(ShortVarDecl
    ,简称变量声明)的末尾开始,并以最内层
    包含块的结尾。


  5. 函数中声明的类型标识符的范围从TypeSpec的标识符开始,并在最内层包含块的结尾
    处结束。

    块中声明的标识符可以在内部块中重新声明。

    内部声明的标识符在范围内,它
    表示由内部声明声明的实体。

package子句不是声明;包名称不会
出现在任何范围内。它的目的是识别属于同一包的
的文件,并指定导入
声明的默认包名称。




优点:$ b​​
$ b

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






  • 在Go中使用不同形式的变量阴影:




    1. Golang限制变量作用域的方式(使用语句中的短语赋值):

        package main 
      importfmt
      func main(){
      i:= 10 // scope:main
      j:= 4
      for i: ='a';我< B; i ++ {
      //我在这个区块内阴影
      fmt.Println(i,j)// 97 4
      }
      fmt.Println(i,j)// 10 4

      if i:=test; len(i)== j {
      //我在这个区块内部被遮蔽
      fmt.Println(i,j)// i = test,j = 4
      } else {
      //我在这个块的内部映射
      fmt.Println(i,j)//测试40
      }
      fmt.Println(i,j)// 10 4
      }


    2. 当我们需要更多字母时,这是极限变量范围

      当您需要更多本地变量或作用域时,此功能也很适用:使用 $ b > {/ code>和} pair:

      优点:不需要额外的语句,如if,for,...


      package main
      importfmt
      func main(){
      i:= 1
      j:= 2
      //新范围:
      {
      i:=hi//新本地var
      j ++
      fmt.Println(i,j)// hi 3
      }
      fmt.Println(i,j)// 1 3
      }


    3. 另一种限制v的方法可用范围是使用函数调用

      优点:范围限制,输入值类型参数可用于局部变量,

      缺点:调用/返回时间,和堆栈使用情况:如果它没有被编译器优化


      $ b

        package main 
      import fmt
      func fun(i int,j * int){
      i ++ // + nice:用作局部变量而没有副作用
      * j ++ // + nice:故意用作全局变量
      fmt.Println(i,* j)// 11 21
      }
      func main(){
      i:= 10 // scope:main
      j:= 20
      fun(i,& j)
      fmt.Println(i,j)// 10 21
      }


    4. 另一种方法是遮蔽全局变量
      $ b

        package main 
      importfmt
      var i int = 1 // global
      func main(){
      j:= 2
      fmt.Println(i,j)// 1 2
      i:= 10 //全局变量shadow
      fmt.Println(i,j)// 10 2
      fun(i,j)// 10 2
      }
      func fun(i,j) int){
      // i:= 100 //错误:左侧没有新变量:=
      // var i int = 100 //错误:我在这个块中重新声明
      fmt.Println(i,j)// 10 2
      }


    请参阅:变量投影范围

    And:声明和范围


    Some related posts I've found:

    Also there are many use cases to Variable Scoping and Shadowing.
    Any code samples or answers will be appreciated.

    解决方案

    Variable scoping and shadowing:

    Go is lexically scoped using blocks:

    1. The scope of a predeclared identifier is the universe block.
    2. 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.
    3. The scope of the package name of an imported package is the file block of the file containing the import declaration.
    4. The scope of an identifier denoting a method receiver, function parameter, or result variable is the function body.
    5. 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.
    6. 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:

    1. 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
      }
      

    2. 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
      }
      

    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 compiler

      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. 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:

    这篇关于我们可以在Go中使用变量范围和阴影吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆