Golang闭包 特性整理

本文通过具体示例介绍了Go语言中的闭包概念及其工作原理。首先展示了如何定义和使用闭包来实现累加器功能,接着对比了闭包与普通函数调用的区别,深入探讨了闭包中的变量作用域及引用行为。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

http://www.cnblogs.com/yjf512/archive/2012/12/09/2810313.html

Go中的闭包

2012-12-09 19:26 by 轩脉刃, 7470 阅读, 0 评论, 收藏编辑

闭包是很多语言必备的功能了,golang也不例外。

先看下面的这个例子:

复制代码
package main

import "fmt"

func adder() func(int) int {
     sum := 0
     return func(x int) int {
          sum += x
          return sum
     }
}

func main() {
     pos, neg := adder(), adder()
     for i := 0; i < 10; i++ {
          fmt.Println(
               pos(i),
               neg(-2*i),
          )
     }
}
复制代码

运行返回结果:

复制代码
0 0
1 -2
3 -6
6 -12
10 -20
15 -30
21 -42
28 -56
36 -72
45 -90
复制代码

这个就是Go中的闭包,一个函数和与其相关的引用环境组合而成的实体。

 

关于闭包的概念《闭包的概念、形式和应用》一文已经说的很清楚了。

 

个人理解: 

其实理解闭包的最方便的方法就是将闭包函数看成一个类,一个闭包函数调用就是实例化一个类。

然后就可以根据类的角度看出哪些是“全局变量”,哪些是“局部变量”了。

比如上例中的adder函数返回func(int) int 的函数

pos和neg分别实例化了两个“闭包类”,在这个“闭包类”中有个“闭包全局变量”sum。所以这样就很好理解返回的结果了。.



golang的闭包和普通函数调用区别

先看一段程序

 http://studygolang.com/articles/356

 

package main


import (
  "fmt"
)

 func main() {
   a := []int{1, 2, 3}
   for _, i := range a {
     fmt.Println(i)
     defer p(i)
   }
 }
 
 func p(i int) {
  fmt.Println(i)
 }

运行这段程序,输出结果为

1

2

3

3

2

1

这里就是普通的函数调用,每次调用func p时,完成 i 的值复制,然后打印,此时 i 值复制了3次,分别是1,2,3。由于defer是后进先出,所以执行变成3,2,1

下面我我们用闭包改写下程序:

package main

import (
  "fmt"
)

func main() {
  a := []int{1, 2, 3}
  for _, i := range a {
    fmt.Println(i)
    defer func() {
       fmt.Println(i)
    }()
    }
}

运行这段程序,输出结果为

1

2

3

3

3

3

这个就是闭包的“神奇”之处。闭包里的非传递参数外部变量值是传引用的,在闭包函数里那个i就是外部非闭包函数自己的参数,所以是相当于引用了外部的变量, i 的值执行到第三次是3 ,闭包是地址引用所以打印了3次i地址指向的值,所以是3,3,3


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值