Golang闭包

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

1 形式含义

聽 聽 所谓闭包就是一个函数“捕获”了和它在同一作用于的其他常量和变量。

聽 聽 从形式上看,在Golang中,所有的匿名函数都是闭包。闭包的创建方式和普通函数几乎一致,只有一个关键区别:闭包没有名字。

聽 聽 我们来看两个例子

addPng聽:=聽func(name聽string)聽string聽{聽return聽name聽+聽".png"聽}
addJpg聽:=聽func(name聽string)聽string聽{聽return聽name聽+聽".jpg"聽}
filename聽:=聽"abc"
fmt.Println(addPng(filename),聽addJpg(filename))

聽 聽 结果如下

wKioL1YfWKXxKfnzAABdlluUiKs571.jpg

//聽工厂函数,返回值也是一个函数
funcaddSuffix(suffix聽string)聽func(string)聽string聽{
聽聽聽聽return聽func(name聽string)聽string聽{
聽聽聽聽聽聽聽聽if聽!strings.HasSuffix(name,聽suffix)聽{
聽聽聽聽聽聽聽聽聽聽聽聽name聽=聽name聽+聽suffix
聽聽聽聽聽聽聽聽}
聽聽聽聽聽聽聽聽return聽name
聽聽聽聽}
}
聽
…
聽
func聽main()聽{
聽聽聽聽聽聽…
聽聽聽聽addZip聽:=聽addSuffix(".zip")
聽聽聽聽addTgz聽:=聽addSuffix(".tar.gz")
聽聽聽聽fmt.Println(addZip(filename),addTgz(filename))
}

wKiom1YfWLfSefPmAABr7vP0oT4056.jpg

2 实质含义

聽 聽 仅仅从形式上将闭包简单理解为匿名函数是不够的,还需要理解闭包实质上的含义。

聽 聽 实质上看,闭包是由函数及其相关引用环境组合而成的实体(即:闭包=函数+引用环境)。闭包在运行时可以有多个实例,不同的引用环境和相同的函数组合可以产生不同的实例。由闭包的实质含义,我们可以推论:闭包获取捕获变量相当于引用传递,而非值传递;对于闭包函数捕获的常量和变量,无论闭包何时何处被调用,闭包都可以使用这些常量和变量,而不用关心它们表面上的作用域。

聽 聽 我们用一个例子来进行验证。

funcaddNumber(x聽int)聽func(int)聽{
聽聽聽聽fmt.Printf("x:聽%d,聽addr聽of聽x:%p\n",聽x,聽&x)
聽聽聽聽return聽func(y聽int)聽{
聽聽聽聽聽聽聽聽k聽:=聽x聽+聽y
聽聽聽聽聽聽聽聽x聽=聽k
聽聽聽聽聽聽聽聽y聽=聽k
聽聽聽聽聽聽聽聽fmt.Printf("x:聽%d,聽addr聽of聽x:%p\n",聽x,聽&x)
聽聽聽聽聽聽聽聽fmt.Printf("y:聽%d,聽addr聽of聽y:%p\n",聽y,聽&y)
聽聽聽聽}
}
聽
func聽main()聽{
聽聽聽聽addNum聽:=聽addNumber(5)
聽聽聽聽addNum(1)
聽聽聽聽addNum(1)
聽聽聽聽addNum(1)
聽
聽聽聽聽fmt.Println("---------------------")
聽
聽聽聽聽addNum1聽:=聽addNumber(5)
聽聽聽聽addNum1(1)
聽聽聽聽addNum1(1)
聽聽聽聽addNum1(1)
}

聽 聽 运行结果

wKioL1YfWpyhwQw6AAGAfOsAGpQ888.jpg

聽 聽 首先强调一点,x是闭包中被捕获的变量,y只是闭包内部的局部变量,而非被捕获的变量。因此,对于每一次引用,x的地址都是固定的,是同一个引用变量;y的地址则是变化的。另外,闭包被引用了两次,由此产生了两个闭包实例,即addNum := addNumber(5)addNum1 :=addNumber(5)是两个不同实例,其中引用的两个x变量也来自两个不同的实例。


本文出自 “说话的白菜” 博客,谢绝转载!


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

本文来自:51CTO博客

感谢作者:说话的白菜

查看原文:Golang闭包

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

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