小谈golang闭包

liugao15 · · 1550 次点击 · · 开始浏览    
这是一个创建于 的文章,其中的信息可能已经有所发展或是发生改变。

    一直用java没用过闭包(我还很菜,可能java也能闭包我不会罢了,希望有人回帖指点),刚接触golang对其闭包机制也挺疑惑。下面写了六个版本的闭包小谈一下。有几个版本摘自别家,看了有段时间我一时不记得来源了很对不起作者了!

版本1:

package main

import "fmt"

func main() {

	var fn [10]func()

	for i := 0; i < len(fn); i++ {
		fn[i] = func() {
			fmt.Println(i)
		}
	}
	
	for _, f := range fn {
		f()
	}
}
结果如下:
10
10
10
10
10
10
10
10
10
10

分析:mian()与func()[]数组构成闭包使用同一个i变量main函数不退出i变量一直存在,f()执行时调用打印语句此时变量i为10。

版本2:
package main

import "fmt"

func main() {
	
	var fn [10]func()
	
	for i := 0; i < len(fn); i++ {
		fn[i] = func() {
			fmt.Println(i)
		}
	}
	
	for i := 0 ; i < len(fn); i++ {
		fn[i]()
	}
}
结果如下:
10
10
10
10
10
10
10
10
10
10

分析:与版本1对比使用显示的i变量做为迭代,但是闭包空间中的i与调用迭代中的i指向内存不同(生存空间也不同)所以使用闭包空间中的i作为打印值为10。

版本3:
package main

import "fmt"

func main() {
	
	var fn [10]func()

	for i := 0; i < len(fn); i++ {
		fn[i] = func() {
			fmt.Println(i)
		}
	}
	
	for j := 0 ; j < len(fn); j++ {
		fn[j]()
	}
}
结果如下:
10
10
10
10
10
10
10
10
10
10

分析:为证明版本2中的分析说法,使用j作为迭代变量,同样打印的10.

版本4:
package main

import "fmt"

func main() {
	
	var fn [10]func()
	var i int
	
	for i = 0; i < len(fn); i++ {
		fn[i] = func() {
			fmt.Println(i)
		}
	}
	
	for i = 0; i < len(fn); i++ {
		fn[i]()
	}
}
结果如下:
0
1
2
3
4
5
6
7
8
9

分析:在main()中声明变量i此时i的生存空间扩大到了main()函数,两次迭代使用同一个i变量。故在第二次迭代时i的迭代当前值会作为打印参数。

版本5:

package main

import "fmt"

func main() {
	
	var fn [10]func()

	for i := 0; i < len(fn); i++ { 
		fn[i] = make_fn(i)
	}
	
	for _, f := range fn {
		f()
	}
}

func make_fn(i int) func() {
	return func() {
		fmt.Println(i)
	}
}
结果如下:
0
1
2
3
4
5
6
7
8
9

分析:在main()函数外定义单独的闭包函数,构成独立的闭包单元,隔离不同func()[]中不同的func()。隔离与独立才是闭包的意义所在,一个表示一系列状态的集合不该在外部为显示通知改变时改变其内部状态。

版本6:

package main

import "fmt"

func main() {
	
	var fn [10]func(int)

	for i := 0; i < len(fn); i++ { 
		fn[i] = make_fn()
	}
	
	for i, f := range fn {
		f(i)
	}
}

func make_fn() func(i int) {
	return func(i int) {
		fmt.Println(i)
	}
}
结果如下:
0
1
2
3
4
5
6
7
8
9

分析:最后这个版本应该为最佳,gotour中的闭包示例使用的正是此中表示方式。     

能力有限只能写这么多了,本人第一次发博支持一下,有意见直说谢谢(漫骂亦可)!


有疑问加站长微信联系(非本文作者)

本文来自:CSDN博客

感谢作者:liugao15

查看原文:小谈golang闭包

入群交流(和以上内容无关):加入Go大咖交流群,或添加微信:liuxiaoyan-s 备注:入群;或加QQ群:692541889

1550 次点击  
加入收藏 微博
暂无回复
添加一条新回复 (您需要 登录 后才能回复 没有账号 ?)
  • 请尽量让自己的回复能够对别人有帮助
  • 支持 Markdown 格式, **粗体**、~~删除线~~、`单行代码`
  • 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
  • 图片支持拖拽、截图粘贴等方式上传