上回函数深度解析给大家聊了一些函数的基本知识,不知道还有没有人记得,不记得赶紧回去复习!

他们是

  • go语言中函数的基本原理
  • 单/多个同/不同类型参数
  • 单/多个同/不同类型返回值
  • 值传递,引用传递
  • 函数进阶,把函数当作变量传递(在不改变函数内部结构的情况下传入新的实现)

匿名函数

话不多说,今天小熊就带各位家人感受下go语言函数中的高级语法。

在前面的文章里我们学会了把函数当作变量传递,可以在不改动原有函数内部实现的情况下,改变函数实现细节(设计模式:装饰器)。

这种情况下的作为变量传递的函数往往只有这一个地方用到了,其他地方不会重复使用。那就没必要单独定义一个函数在外面!(多此一举的事本熊不做!)

like this:

func functionValue(a, b int,    do func(int, int) int) { fmt.Println(do(a, b))}

//使用匿名函数的方法调用他 实现匿名加函数funcationValue(1,2,func(a,b int) int{return a+b })//使用匿名函数的方法调用他 实现匿名减函数funcationValue(1,2,func(a,b int) int{return a-b })

在调用的时候我们才实现了一个匿名函数(没有名字的函数)

那是不是只有把函数当变量传递的时候才用到匿名函数呢?并,不,是!

各位同学,让我上黑板给大家实现一个简单的匿名函数用法。

f := func(i int) {  fmt.Println(i) }

f(1)

把匿名函数赋值给一个变量(这里是f),f就是他的函数名,后面就可以直接调用啦~,但是这种简单使用的情况实际上会不会用到呢?很残酷,几乎没有。

匿名函数配合下面的场景使用效果更佳。

闭包

你有没有一种情况,常常要定义好多全局变量来共享数据,这种变量一旦多了非常难看,还会污染环境,有没有一种办法,可以通过重复调用同一个函数,来修改函数内部的变量呢?

我翻来覆去发现是真的有!这个东西就叫闭包!


闭包的简单实现,把函数定义在函数内部,并当作返回值返回。

func closureSample() func() { count := 0 return func() {  count ++  fmt.Printf("调用次数 %v \n", count) }}

怎么用才爽?我先丧心病狂的调用两次closureSample函数,得到两个函数c1c2,这两个函数就是closureSample函数的返回值,类型是一个匿名函数。

c1, c2 := closureSample(), closureSample()

疯狂调用!!!


 c1() c1() c1() // 你会发现c2又从1开始输出,因为两个函数的变量是独立使用的 c2() c2()

输出

调用次数 1调用次数 2调用次数 3调用次数 1调用次数 2调用次数 3

神奇不神奇!在调用c2的时候,完全没有影响到c1

这是因为各个函数是独立使用一套自己的内部变量,互相不影响,所以闭包也可以当测试用例使用。

用来传入不同的实现,重复调用得到不同的返回,不用定义全局变量。

  • 好处:可以减少全局变量防止变量污染
  • 坏处:延长了局部变量和函数的生命周期,增加了 gc 的压力

闭包形式 2

通过上面的例子,不难发现闭包内部的匿名函数可以使用到外部的变量。

闭包形式 2,立即执行函数,声明完以后加括号,用以表示即刻调用。

func() {  // to do something }()

闭包存在的 bug

go 里创建一个协程(类似于子线程)非常的容易,只要在语句前加一个go关键字就可以了。看看下面这个函数会出现什么问题。

for i := 0; i 3; i++ {  fmt.Printf("第一次 i 产生变化中 %v \n", i)  go func() {   fmt.Printf("第一次输出: %v\n", i)  }() } time.Sleep(time.Second)

协程创建完以后立即会执行,但是协程创建这个事件和协程执行代码是分离的,他可以全部创建完再执行,而且主线程和协程是同时运行的(并发),有可能主线程执行完了,协程还没执行。

这个时候协程才会调用外部的变量,i 已经变成 3 了。

第一次 i 产生变化中 0第一次 i 产生变化中 1第一次 i 产生变化中 2第一次输出:3第一次输出:3第一次输出:3

解决办法,创建副本,可以给匿名函数加一个参数,传值过来自动生成副本

for i := 0; i 3; i++ {  fmt.Printf("第二次 i 产生变化中 %v \n", i)  go func(tmp int) {   fmt.Printf("第二次输出: %v\n", tmp)  }(i) }time.Sleep(time.Second)

输出

第二次 i 产生变化中 0第二次 i 产生变化中 1第二次输出:0第二次 i 产生变化中 2第二次输出:2第二次输出:1

第二种创建副本的形式

for i := 0; i 3; i++ {  fmt.Printf("第三次 i 产生变化中 %v \n", i)  tmp := i  go func() {   fmt.Printf("第三次输出: %v\n", tmp)  }() } time.Sleep(time.Second)

输出

第三次 i 产生变化中 0第三次 i 产生变化中 1第三次 i 产生变化中 2第三次输出: 0第三次输出: 2第三次输出: 1

推荐阅读

  • Go语言函数深度解析(上)


喜欢本文的朋友,欢迎关注“Go语言中文网”:

Go语言中文网启用微信学习交流群,欢迎加微信:274768166,投稿亦欢迎

如有收获,点个在看,诚挚感谢

语言中拟合函数 计算aic_Go语言函数深度解析(中)相关推荐

  1. crc16的c语言函数 计算ccitt_C语言为何如此重要

    ●●● 如今,有很多学生不懂为何要学习编程语言,为何要学习C语言?原因是大学生不能满足于只会用办公软件,而应当有更高的学习要求,对于理工科的学生尤其如此.计算机的本质是"程序的机器" ...

  2. 工测中坐标方位角的计算c语言,工程测量中坐标方位角是怎么进行推算的?

    原标题:工程测量中坐标方位角是怎么进行推算的? 在工程测量中很多测量人员都觉得坐标方位角难以理解,从而也不明白工程测量中坐标方位角是怎么进行推算的.所以本文详细解释一下坐标方位角的概念,以及坐标方位角 ...

  3. 使用函数计算三步实现深度学习 AI 推理在线服务

    目前深度学习应用广发, 其中 AI 推理的在线服务是其中一个重要的可落地的应用场景.本文将为大家介绍使用函数计算部署深度学习 AI 推理的最佳实践,  其中包括使用 FUN 工具一键部署安装第三方依赖 ...

  4. 本地函数定义是非法的_使用函数计算三步实现深度学习 AI 推理在线服务

    目前深度学习应用广发, 其中 AI 推理的在线服务是其中一个重要的可落地的应用场景.本文将为大家介绍使用函数计算部署深度学习 AI 推理的最佳实践, 其中包括使用 FUN 工具一键部署安装第三方依赖. ...

  5. 条件表达式计算个人所得税c语言,个税的计算C语言实现,结果为什么是负的?...

    个税的计算C语言实现,结果为什么是负的?0 /*运算结果: please input your profit every month 9876 the tax of 9876 is -479.80 请 ...

  6. c语言允许用户重复计算,C语言-第3章最简单的C程序设计练习题.doc

    C语言-第3章最简单的C程序设计练习题 第3章 最简单的C程序设计-顺序程序设计 一.单项选择题 1. 不是C语言提供的合法关键字是 . A)switch B)cher C)case D)defaul ...

  7. 《离散制造业边缘计算解决方案白皮书》深度解析

    2020年4月,中国信息通信研究院联合工业互联网产业联盟共同发布<离散制造业边缘计算解决方案白皮书> 白皮书内容来源: http://www.aii-alliance.org/bps/20 ...

  8. 计算机基础知识教程excel函数计算,计算机基础知识:Excel中的函数操作(四)...

    [导语]在事业单位考试中,计算机专业知识的复习向来是考生复习备考阶段的一大重点,其中中公事业单位考试网为计算机基础知识的复习为考生提供知识点梳理,帮助考生备考! 一.CONCATENATE函数 函数名 ...

  9. c语言字符型常量计算,c语言字符型常量和变量.doc

    c语言字符型常量和变量 谅娄协逞妥唐氦错赵夏教灶技竞白量菲荚锚坤缆咕囤厢失随着牲淋我雾谋蹬格椭金佃贮官梳冕萨鱼疥卫答襟回咬逢砾摘宛嵌拎宛拽抱钢簧彩城挛霉门窗莉辉托罚椽建呛液汛炕午望延晒纠挺谱阔衔解抗贱 ...

最新文章

  1. DeepID3:Face Recognition with Very Deep Neural Networks
  2. Windows消息:怎样使用RegisterWindowMessage注册消息
  3. react+redux使用static mapStoreToProps
  4. 分享一套阿里高级Java面试题,要去阿里的先过这些题。
  5. SQL Server 相关create操作语句
  6. windows服务编程 注册InstallUtil.exe
  7. mysql limit 不起作用_这句mysql中为什么limit起不到作用
  8. 影院售票系统-----一个让你有成就感的小项目,只有一丢丢哦
  9. 手把手教你上手Proteus(下载安装+仿真51单片机程序)
  10. Android 官方独立 adb / fastboot 工具包
  11. 【开源】有手就能做的街机游戏
  12. 西宝高速公路模拟java大作业_——访西宝高速公路改扩建项目管理处处长王剑...
  13. 基于Scrapy框架对二手车数据进行挖掘
  14. linux能远程开机么,Linux下如何实现远程开机
  15. CSS3的新特性:css响应式多列布局、断字
  16. deel t410安装_用DEEL-LIP构建Lipschitz约束网络
  17. E9000刀片服务器维护记录
  18. 农业遥感技术科研成果汇总
  19. /var/spool/postfix/maildrop占用空间大量处理
  20. 第五章 生活无处不数据,大数据真的能算命?

热门文章

  1. CSS定位网页中的元素
  2. Apache状态监测集重启
  3. Json.NET Deserialize时如何忽略$id等特殊属性
  4. SQL 批量插入有标识列的数据
  5. Struts1 中的 global-forward
  6. 火星人敏捷开发手册 原10.31版本已于10.14提前发布,特此通知
  7. UNREFERENCED_PARAMETER的作用
  8. 强烈推荐——微软一站式开发技术框架 All-In-One Code Framework (CodeFx)
  9. 什么是云计算机服务器,云电脑服务器是什么
  10. kmeans中的k的含义_聚类的Python实现(二):确定分群数K