美文网首页
Go基础-012 标识符作用域与闭包

Go基础-012 标识符作用域与闭包

作者: 如逆水行舟不进则退 | 来源:发表于2020-02-24 21:36 被阅读0次

1. 作用域

标识符的可见性。主要是变量,常量。当定义好标识符(变量)后,在什么位置可以使用。就是作用域 scope 的问题。

作用域主要点:

  • 块级作用域。在语句块中声明的变量,仅仅在该语句块中有效。语句块,{} 定义
    的就是语句块,包括函数,if, swtich,for, for..range 语句结构,和独立的大括号。
  • 作用域是嵌套的。内层作用域可以访问外层作用域的标识符(变量)。例如函数中 if 语句块,可以访问函数中定义的变量。若出现内外层重名的标识符,优先访问所 在作用域的标识符。
  • 定义的变量,仅可以在当前块及其内部块访问到。
  • 定义在函数外的标识符称之为全局标识符。全局,仅可以在当前包中访问,其他包
    中需要通过包名来引用才可以访问。

2.闭包现象

closure
当作用域是嵌套情况下时(go 语言就是嵌套的),内层作用域(语句块)使用外层作用域的变量,当外层语句块运行结束后,如果内层语句块还可以被使用,则内层语句块与外层 变量构成了闭包。闭包现象会导致,外层语句中定义的变量,不会立即被释放。

演示:

func outer() func() { 
  n := 42
  return func() {
      n ++ // 使用外层变量
      fmt.Println(n) 
    }
 }
  f := outer()
  // outer()运行结束,外层语句块 
  f() // 42

上面的代码中,内层函数就与外层 outer()定义的变量 n 形成了闭包,n 不会随着 outer()的运 行结束而释放。
Go 语言支持闭包!没有好坏!

闭包,将一组数据和一些操作组合在了一起,也被称作带有数据的操作。(面向对象编程,
带有操作的数据),体现了数据的实体性。

由于闭包可以将数据和操作绑定在一起,完成一些特定的封装业务逻辑,演示做一个计数器, 使用全局变量的方案:

// 全局变量 counter 用于计数
var counter = 0
func CounterIncr() {
  counter ++ 
}
func CounterDecr() {
  counter -- 
}

该方案致命的问题是,counter 这个变量,不仅仅 CounterIncr() CunterDecr()可用,任何代码 都可用,不能保证 couter 变量的准确性。如何才能将 counter 与具体的操作函数绑定在一起 呢?只能某些个函数可以操作 counter。
利用闭包来实现,利用闭包来实现封装的计数器。

func CounterInit(initValue int) (func(), func(), func() int) {
 counter := initValue
  return func() {
      counter ++ 
  }, func() {
      counter -- 
  }, func() int {
       return counter
  } 
}
CounterIncr, CounterDecr, CounterGetter := CounterInit(0) 
fmt.Println(CounterGetter())
CounterIncr()
CounterIncr()
CounterDecr() 
fmt.Println(CounterGetter())

相关文章

网友评论

      本文标题:Go基础-012 标识符作用域与闭包

      本文链接:https://www.haomeiwen.com/subject/fgtiqhtx.html