登录
首页 >  Golang >  Go教程

go语言中匿名函数的作用域陷阱详解

来源:脚本之家

时间:2022-12-30 19:55:56 457浏览 收藏

对于一个Golang开发者来说,牢固扎实的基础是十分重要的,golang学习网就来带大家一点点的掌握基础知识点。今天本篇文章带大家了解《go语言中匿名函数的作用域陷阱详解》,主要介绍了go语言匿名函数、作用域,希望对大家的知识积累有所帮助,快点收藏起来吧,否则需要时就找不到了!

众所周知在go语言中函数也可以当作变量在程序中使用,我们可以使用函数字面量在任何表达式内指定函数变量。但是在编写代码的时候请注意:如果一个函数在使用不是在该函数内部定义的变量时,这个变量的生命周期不是由其作用域决定的!

这段话什么意思呢,借鉴go语言圣经中的一段代码举个例子:

func square() func() int { //返回一个自己定义的函数类型
   var x int = 0
   return func() int {
      x++
      return x
   }
}
func main() {
   f := square()     
   fmt.Println(f()) // 1
   fmt.Println(f()) // 2
   fmt.Println(f()) // 3
   fmt.Println(f()) // 4
}

在这段程序中,函数square返回了一个类型为func() int的函数类型,但在每次调用f()的时候,匿名函数内部都会在x原有的值的基础上+1来更新x的值,而不是把x值赋值为0,所有这段代码最终的执行结果为1 2 3 4。

这表明里层的匿名函数能获取和更新外层的square函数的局部变量,变量x在main函数中返回square函数后依然存在。我们可以将其类比为全局变量和函数的关系来理解:把square函数看作一个独立的go程序,那么局部变量x可视为在square函数内部的全局变量,显然匿名函数每次操作的都是同一个变量。我们加上变量的地址输出验证是否正确:

func square() func() int { //返回一个自己定义的函数类型
   var x int = 0
   return func() int {
      x++
      fmt.Println(&x)
      return x
   }
}
func main() {
   f := square()
   fmt.Println(f()) 
   fmt.Println(f()) 
   fmt.Println(f()) 
   fmt.Println(f()) 
}

结果:

可见调用的变量x的确是同一个变量,那么我们在捕获迭代变量时使用匿名函数的时候就需要小心,看下面这段程序:

func square(x int) int { 
   fmt.Println(x)
   return x
}
func main() {
   var handlers []func()
   for i := 0; i 

在这段程序中,变量i在for循环引进的一个块作用域进行声明,根据前面的经验我们可以知道:在循环里创建的所有函数变量共享相同的变量,i的值在迭代中不断更新,因此i的实际取值是循环中i的最后一个取值,并且所有的square函数都在处理同一个值,运行结果也可以证明这一点:

我们经常引入一个内部变量来解决这个问题,声明一个副本,并将这个副本的值传入而不是直接把i的值传入:

func square(x int) int {
   fmt.Println(x)
   return x * x
}
func main() {
   var handlers []func()
   for i := 0; i 

这样就得到了我们想要的运行结果:

总结

终于介绍完啦!小伙伴们,这篇关于《go语言中匿名函数的作用域陷阱详解》的介绍应该让你收获多多了吧!欢迎大家收藏或分享给更多需要学习的朋友吧~golang学习网公众号也会发布Golang相关知识,快来关注吧!

声明:本文转载于:脚本之家 如有侵犯,请联系study_golang@163.com删除
相关阅读
更多>
最新阅读
更多>
课程推荐
更多>