关于闭包有句话说的很好,闭包捕获的变量和常量是引用传递不是值传递。

Go语言支持匿名函数,即函数可以像普通变量一样被传递或使用。

使用方法如下:

package main

import (
"fmt"
) func main() {
var v func(a int) int
v = func(a int) int {
return a * a
}
fmt.Println(v(6))
//两种写法
v1 := func(i int) int {
return i * i }
fmt.Println(v1(7))
}

  

GO语言的匿名函数就是闭包,以下是《GO语言编程》中对闭包的解释

基本概念
闭包是可以包含自由(未绑定到特定对象)变量的代码块,这些变量不在这个代码块内或者
任何全局上下文中定义,而是在定义代码块的环境中定义。要执行的代码块(由于自由变量包含
在代码块中,所以这些自由变量以及它们引用的对象没有被释放)为自由变量提供绑定的计算环
境(作用域)。
 闭包的价值
闭包的价值在于可以作为函数对象或者匿名函数,对于类型系统而言,这意味着不仅要表示
数据还要表示代码。支持闭包的多数语言都将函数作为第一级对象,就是说这些函数可以存储到
变量中作为参数传递给其他函数,最重要的是能够被函数动态创建和返回。

一个函数和与其相关的引用环境,组合而成的实体:

package main

import "fmt"

func main() {
var f = Adder()
fmt.Println(f(1), "-")
fmt.Println(f(20), "-")
fmt.Println(f(300), "-") }
func Adder() func(int) int {
var x int
return func(delta int) int {
x += delta
return x
}
}

  

使用闭包的注意点

(1)由于闭包会使得函数中的变量都被保存在内存中,内存消耗很大,所以不能滥用闭包,否则会造成网页的性能问题,在IE中可能导致内存泄露。解决方法是,在退出函数之前,将不使用的局部变量全部删除。

(2)闭包会在父函数外部,改变父函数内部变量的值。所以,如果你把父函数当作对象(object)使用,把闭包当作它的公用方法(Public Method),把内部变量当作它的私有属性(private value),这时一定要小心,不要随便改变父函数内部变量的值。

闭包的注意点

由于闭包使的函数的变量保存在内中,会出现值被替换的情况

package main

import "fmt"

func main() {
var flist []func()
for i := 0; i < 3; i++ {
flist = append(flist, func() {
fmt.Println(i)
})
} for _, f := range flist {
f()
}
}

  我们可以看到结果全是3。为什么呢?我们可以打印下循环中i的地址

package main

import "fmt"

func main() {
var flist []func()
for i := 0; i < 3; i++ {
fmt.Println(&i) flist = append(flist, func() {
fmt.Println(i)
})
} for _, f := range flist {
f()
}
}

  发现运行的结果

0xc0420080a8
0xc0420080a8
0xc0420080a8
3
3
3

  i指向的地址是一样的,那么就很明了了i的变量被保存了,最后的循环把i的值变成了3

如何改进呢,我们只需要每次初始化一个i就可以了

package main

import "fmt"

func main() {
var flist []func()
for i := 0; i < 3; i++ { i := i //给i变量重新赋值,
fmt.Println(i)
flist = append(flist, func() {
fmt.Println(i)
})
}
for _, f := range flist {
f()
}
}

  

go语言学习--go中闭包的更多相关文章

  1. go语言学习--go中godep的使用小结

    go中的godep 本文参考:http://www.cnblogs.com/me115/p/5528463.html#h20 http://studygolang.com/articles/4385 ...

  2. go语言学习--map中键值得删除

    测试 map1 中是否存在 key1: 在例子 8.1 中,我们已经见过可以使用 val1 = map1[key1] 的方法获取 key1 对应的值 val1.如果 map 中不存在 key1,val ...

  3. go语言学习--go中的map切片

    //定义一个结构 type Car struct { Brand string Age int } func Pluck() map[int][]Car { carMap := make(map[in ...

  4. 大一C语言学习笔记(5)---函数篇-定义函数需要了解注意的地方;定义函数的易错点;详细说明函数的每个组合部分的功能及注意事项

    博主学习C语言是通过B站上的<郝斌C语言自学教程>,对于C语言初学者来说,我认为郝斌真的是在全网C语言学习课程中讲的最全面,到位的一个,这个不是真不是博主我吹他哈,大家可以去B站去看看,C ...

  5. R语言学习笔记——C#中如何使用R语言setwd()函数

    在R语言编译器中,设置当前工作文件夹可以用setwd()函数. > setwd("e://桌面//")> setwd("e:\桌面\")> s ...

  6. 如何设计一门语言(七)——闭包、lambda和interface

    人们都很喜欢讨论闭包这个概念.其实这个概念对于写代码来讲一点用都没有,写代码只需要掌握好lambda表达式和class+interface的语义就行了.基本上只有在写编译器和虚拟机的时候才需要管什么是 ...

  7. go语言学习笔记

    Go语言学习基本类型Bool 取值范围:true,false (不可以用数字代替)Int/uint 根据平台可能为32或64位int8/uint8 长度:1字节 取值范围-128~127/0~255b ...

  8. Go语言学习笔记七: 函数

    Go语言学习笔记七: 函数 Go语言有函数还有方法,神奇不.这有点像python了. 函数定义 func function_name( [parameter list] ) [return_types ...

  9. 如何理解并学习javascript中的面向对象(OOP) [转]

    如果你想让你的javascript代码变得更加优美,性能更加卓越.或者,你想像jQuery的作者一样,写出属于自己优秀的类库(哪怕是基于 jquery的插件).那么,你请务必要学习javascript ...

随机推荐

  1. gcd(1,n)+gcd(2,n)....gcd(n-1,n); Uva11426

    #include<bits/stdc++.h> #define int long long using namespace std; ; int phi[maxn]; int prime[ ...

  2. Centos7安装32位库用来安装32位软件程序

    打算在centos7上安装一个远程控制软件,发现teamviewer只有centos的32位版本,试着安装了一下,各种报错,尝试多次无果.于是试着用向日葵远程控制软件,也报错,貌似也是只支持32位. ...

  3. Centos7禁止或者允许开机启动服务

    [root@bogon rsyslog.d]# systemctl is-enabled httpd disabled [root@bogon rsyslog.d]# systemctl status ...

  4. malloc,calloc,alloca和free函数

    void *malloc(size_t size)因为返回类型为空,所以可以赋值到任何类型指针,其分配的空间大小为size,返回新分配内存地址的起始处的指针,其所分配的内存未经初始化,若分配失败返回N ...

  5. JQuery注册页面表单检验完善

    <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title> ...

  6. Java中的权限学习笔记

    1.Java中的权限有两个层次,一个是类这一层,另一个是类成员那一层. 类这一层: public class可以在本包内被访问,也可以在包外被访问.而没有被public修饰的class只能在本包内被调 ...

  7. java保留2位小数及BigDecimal使用

    java保留两位小数的方法 import java.math.BigDecimal; import java.text.DecimalFormat; import java.text.NumberFo ...

  8. How To Use the AWK language to Manipulate Text in Linux

    https://www.digitalocean.com/community/tutorials/how-to-use-the-awk-language-to-manipulate-text-in-l ...

  9. Lambda 表达式 是 个 好东东

    Lambda 表达式 是 个 好东东 首先,通过 Lambda 表达式 + 动态语言特性 dynamic , C# 已经 可以 实现 函数式 编程 了 其次, 利用 Lambda, 可以 实现 AOP ...

  10. secureCRT 设置证书免密登陆

    1 第一步 2 第二步 3 第三步 4 第4 步 ,然后选择你的 私钥文件