go:匿名函数与闭包
一、匿名函数
定义:没有函数名的函数。
作用:在go语言中目前了解的作用就是用于构成闭包。
*注:由于javascript不存在块级作用域,故匿名函数常用来包含代码以不污染全局命名空间,运行后销毁环境。
----来自知乎回答:http://www.zhihu.com/question/34649602
使用方法及其原理请参考:http://www.cnblogs.com/chenxianbin89/archive/2010/01/28/1658392.html
使用举例
(1)
a := func() {
fmt.Println(1)
}
a() //输出:1
(2)带参数
b := func(arg int) {
fmt.Println(arg)
}
b(2) //输出:2
(func(arg int) {
fmt.Println(arg)
})(3) //输出:3
(3)带返回值
c := func() int {
fmt.Println(4)
return 5
}
d := c() //打印输出4,并将5赋值给d
fmt.Println(d)
二、闭包(closure)
闭包的理解参考:http://www.cnblogs.com/mzwr1982/archive/2012/05/20/2509295.html
闭包的用途参考:http://blog.csdn.net/sunlylorn/article/details/6534610
和 http://www.cnblogs.com/rainman/archive/2009/05/04/1448899.html
简单来说:
因为把返回的函数赋给了一个变量,虽然函数在执行完一瞬间会销毁其执行环境,
但是如果有闭包的话,闭包会保存外部函数的活动对象(变量),所以如果不把对闭包的引用消除掉,
闭包会一直存在内存中,垃圾收集器不会销毁闭包占用的内存。
----来自知乎回答http://www.zhihu.com/question/34649602
使用举例
(1)
//函数A是一个不带参数,返回值是一个匿名函数,且该函数
//带有一个int类型参数,返回值为一个int类型
func A() func(aa int) int {
sum := 0
return func(cc int) int {
sum += cc
fmt.Println("aa=", aa, "bb=", bb, " sum=", sum)
return sum
}
}//编译错误,提示aa未定义
实际上func(aa int) int只是函数A的返回值,在这里给参数取名无任何作用,反而会影响代码阅读,直接用func(int) int 即可。
更正后:
func A() func(int) int {
sum := 0
return func(bb int) int {
sum += bb
fmt.Println("bb=", bb, "\tsum=", sum)
return sum
}
}
调用1:
func main() {
a := A()//定义变量a,并将函数A的返回值赋给a
b := a(4)
fmt.Println(b)
}
/*
** 输出:
** bb= 4 sum= 4
** 4
*/
调用2:
func main() {
a := A()
a(0)
a(1)
a(5)
}
/*
** 输出:
** bb= 0 sum= 0
** bb= 1 sum= 1
** bb= 5 sum= 6
*/
以上调用通过闭包实现了sum的累加
调用3:
func main() {
a := A()
c := A()
a(0)
a(5)
c(10)
c(20)
}
/*
** 输出:
** bb= 0 sum= 0
** bb= 5 sum= 5
** bb= 10 sum= 10
** bb= 20 sum= 30
*/
可以看出,上例中调用了两次函数A,构成了两个闭包,这两个闭包维护的变量sum不是同一个变量。
(2)
func B() []func() {
b := make([]func(), 3, 3)
for i := 0; i < 3; i++ {
b[i] = func() {
fmt.Println(i)
}
}
return b
}
func main() {
c := B()
c[0]()
c[1]()
c[2]()
}
/*
** 输出:
** 3
** 3
** 3
*/
闭包通过引用的方式使用外部函数的变量。
上例中只调用了一次函数B,构成一个闭包,i 在外部函数B中定义,所以闭包维护该变量 i ,c[0]、c[1]、c[2]中的 i 都是闭包中 i 的引用。
因此执行c:=B()后,i 的值已经变为3,故再调用c[0]()时的输出是3而不是0。
可作如下修改:
func B() []func() {
b := make([]func(), 3, 3)
for i := 0; i < 3; i++ {
b[i] = (func(j int) func() {
return func() {
fmt.Println(j)
}
})(i)
}
return b
}
func main() {
c := B()
c[0]()
c[1]()
c[2]()
}
/*
** 输出:
** 0
** 1
** 2
*/
以上修改可能没有什么实际意义,此处仅为说明问题使用。
在使用defer的时候可能出现类似问题,需要注意:
for j := 0; j < 2; j++ {
defer (func() {
fmt.Println(j)
})()
}
/*
** 输出:
** 2
** 2
*/
go:匿名函数与闭包的更多相关文章
- JavaScript笔记 第十六章 匿名函数和闭包
1.匿名函数 2.闭包 匿名函数就是没有名字的函数,闭包是可访问一个函数作用域里变量的函数. 一.匿名函数 //普通函数 function getName() { return 'name'; } a ...
- 第一百一十节,JavaScript匿名函数和闭包
JavaScript匿名函数和闭包 学习要点: 1.匿名函数 2.闭包 匿名函数就是没有名字的函数,闭包是可访问一个函数作用域里变量的函数.声明:本节内容需要有面向对象和少量设计模式基础,否则无法听懂 ...
- JavaScript(第十五天)【匿名函数和闭包】
学习要点: 1.匿名函数 2.闭包 匿名函数就是没有名字的函数,闭包是可访问一个函数作用域里变量的函数.声明:本节内容需要有面向对象和少量设计模式基础,否则无法听懂.(所需基础15章的时候已经声明 ...
- 从匿名函数(闭包特性)到 PHP 设计模式之容器模式
匿名函数(匿名函数) 匿名函数,也叫闭包函数,它允许临时创建一个没有指定名称的函数,常用作回调函数参数的值,也可以作为变量的值来使用.具体的使用见以下示例代码: /* 示例一:声明一个简单匿名函数,并 ...
- php的匿名函数和闭包函数
php的匿名函数和闭包函数 tags: 匿名函数 闭包函数 php闭包函数 php匿名函数 function use 引言:匿名函数和闭包函数都不是特别高深的知识,但是很多刚入门的朋友却总是很困惑,因 ...
- js匿名函数和闭包总结
js匿名函数和闭包总结 一.总结 一句话总结:匿名函数的最主要作用是创建闭包,闭包就是将函数内部和函数外部连接起来的一座桥梁.内层的函数可以使用外层函数的所有变量,即使外层函数已经执行完毕.闭包可以用 ...
- 匿名函数、闭包、lambda表达式、Block
C#有lambda.匿名函数,js有匿名函数.闭包,OC中有block,看到这是不是心中有一万个草泥马在跑,不过它们这些都是换汤不换药,不同语言名字不一样. 从功能性上说lambda和closure( ...
- Golang之匿名函数和闭包
Go语言支持匿名函数,即函数可以像普通变量一样被传递或使用. 使用方法如下: main.go package main import ( "fmt" ) func main() { ...
- js循环函数中的匿名函数和闭包问题(匿名函数要用循环中变量的问题)
js循环函数中的匿名函数和闭包问题(匿名函数要用循环中变量的问题) 一.总结 需要好好看下面代码 本质是因为匿名函数用到了循环中的变量,而普通方式访问的话,匿名函数的访问在循环之后,所以得到的i是循环 ...
- javascript进阶课程--第三章--匿名函数和闭包
javascript进阶课程--第三章--匿名函数和闭包 一.总结 二.学习要点 掌握匿名函数和闭包的应用 三.匿名函数和闭包 匿名函数 没有函数名字的函数 单独的匿名函数是无法运行和调用的 可以把匿 ...
随机推荐
- Linux 中 Nginx 重启关闭
如果服务器正在运行的 Nginx 要进行升级.添加或删除模块时. 我们需要停掉服务器并做相应修改,这样服务器就要在一段时间内停止服务. Nginx可以在不停机的情况下进行各种升级动作而不影响服务器运行 ...
- ASP.NET中的缓存机制
ASP.NET 提供一个功能完整的缓存引擎,页面可使用该引擎通过 HTTP 请求存储和检索任意对象.缓存的生存期与应用程序的生存期相同,也就是说,当应用程序重新启动时,将重新创建缓存. 将数据添加到缓 ...
- Java使用代理服务器
HTTP协议是基于TCP协议的,TCP协议在Java中的体现就是套接字.在了解HTTP协议的基础上,完全可以通过TCP来实现一套HTTP库,这个库可以发起网络请求和接受网络请求.只要能用URLConn ...
- 第五次团队作业——【Alpha版本】随笔汇总
031402304 陈燊 031402342 许玲玲 031402337 胡心颖 03140241 王婷婷 031402203 陈齐民 031402209 黄伟炜 031402233 郑扬涛 [Alp ...
- ASP.NET Identity系列教程(目录)
$(document).ready(function(){ $("#hide").click(function(){ $(".en").hide(); }); ...
- 递推 hdu 2048
t 关于错排 共n个数 第n个 和一个交换 其他n-2错排 (n-1)*z[n-2]; n-1个错排 第n个和n-1个交换 (n-1)*z[n-1]; 求和 然后概率的话要除n! 一个一个除 ...
- 教你一招:Word中的文字转换成表格,把表格转换成文字
在使用office软件时,常常会在Word中加入表格,这时候我们一般想到的是,建立表格,然后一格一格的填写;或者用Excel表格制作在复制到Word文档中.其实在Word中就可以将文本文档转换成电子表 ...
- Python 从零学起(纯基础) 笔记 之 迭代器、生成器和修饰器
Python的迭代器. 生成器和修饰器 1. 迭代器是访问集合元素的一种方式,从第一个到最后,只许前进不许后退. 优点:不要求事先准备好整个迭代过程中的所有元素,仅仅在迭代到某个元素时才计算该元素,而 ...
- JAVA之IO流(字节流)
输入和输出 JAVA的流分为输入流和输出流两部分, 输入流:InputStream或者Reader:从文件中读到程序中: 输出流:OutputStream或者Writer:从程序中输出到文件中: Re ...
- python学习笔记-(十二)scoket编程基础
socket通常也称作"套接字",用于描述IP地址和端口,是一个通信链的句柄,应用程序通常通过"套接字"向网络发出请求或者应答网络请求. socket起源于Un ...