doudi1978 2016-04-11 15:37
浏览 42

我们在哪里可以在Go中使用可变作用域和阴影?

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.

  • 写回答

1条回答 默认 最新

  • douben7493 2016-04-11 15:37
    关注

    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:

    评论

报告相同问题?

悬赏问题

  • ¥15 目详情-五一模拟赛详情页
  • ¥15 有了解d3和topogram.js库的吗?有偿请教
  • ¥100 任意维数的K均值聚类
  • ¥15 stamps做sbas-insar,时序沉降图怎么画
  • ¥15 买了个传感器,根据商家发的代码和步骤使用但是代码报错了不会改,有没有人可以看看
  • ¥15 关于#Java#的问题,如何解决?
  • ¥15 加热介质是液体,换热器壳侧导热系数和总的导热系数怎么算
  • ¥100 嵌入式系统基于PIC16F882和热敏电阻的数字温度计
  • ¥15 cmd cl 0x000007b
  • ¥20 BAPI_PR_CHANGE how to add account assignment information for service line