Go语言之匿名函数和C++的lambda表达式

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

微信公众号 原文链接:https://mp.weixin.qq.com/s/f0St4CioNc8QZHK4jop-3g #一、Go语言中的匿名函数 指的是不需要有名字的函数,通常定义在另外一个函数内部。 ###格式: func (参数列别)(返回值列表) { } 例子: ``` package main import ( "fmt" ) func main() { Sum := func(l, r int) (sum int) { sum = l + r return } // 备注:变量Sum作为匿名函数来使用,求和 fmt.Println("Hello, sum Address: sum!", &Sum, Sum(50,10)) return } Output: Hello, sum Address: sum! 0x40c128 60 ``` ###使用场景: 匿名函数通常比较短小,不希望在这个函数外部使用,这点类似与C++中的lamdba表达式。 ###补充说明: 匿名函数也可以实现成一个函数数组,使用者可以根据不同的indx来调用不同的匿名函数,这样的话,使用者可以根据自己的需要灵活的使用这些匿名函数。 例子: ``` package main import ( "fmt" ) func main() { funcs := [](func(str string) string){ // 备注:这里面实现了3个不同的函数 func(str string) string { return "Format 1: " + str }, func(str string) string { return "Format 2: " + str }, func(str string) string { return "Format 3: " + str }, } for idx, fun := range funcs { fmt.Println("Hello, funcs idx, result:", idx, fun("World")) } return } output: Hello, funcs idx, result: 0 Format 1: World Hello, funcs idx, result: 1 Format 2: World Hello, funcs idx, result: 2 Format 3: World ``` #二、C++中的lambda表达式 C++ 中的lambda表达式是在C++ 11之后才出现的,(备注:这里也只介绍C++ 11)官方文档上说它是闭包类型,笔者个人觉得可以把它理解为一个函数,不过这个函数,有下面一些特性。 1.是函数内部的函数,作用域在这个函数内部,出了该函数之后,不能使用。 2.lambda表达式所表示的函数,是没有名字的。 3.通常这个lambda表达式所做的事情,短小精悍。 为什么我们需要lambda表达式? 笔者觉得lambda表达式之所以存在的主要原因,是因为函数内部的一部分代码,复用率很高,但是也只是在这个函数内部使用,其他函数并不会使用。 这样就导致了一个尴尬的局面,写成一个单独的函数吧,作用范围有些广泛,不写成函数吧,函数内部要写多份相同的代码,于是lambda表达式产生了。 lambda的编译是当作函数来编译的,识别方法是,编译器看到[的时候就知道是lambda表达式了,然后按照lambda表达式的规则来编译。 如何使用lambda表达式? 1.lambda表达式的格式 [ captures ] ( params ) -> ret { body } // 带参数和返回值的表达式 [ captures ] ( params ) { body } // 没有返回值的表达式 [ captures ] { body } // 无参数也无返回值的表达式 captures叫做俘获符,params是形式参数,ret 是返回类型,body表示函数体(备注:captures比较复杂,稍后介绍,其他的都比较容易理解。) 俘获符介绍详细如下所示: ![image.png](https://upload-images.jianshu.io/upload_images/4698491-a6388d5b9fb3f232.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240) 2. 例子 1) . [] //未定义变量.试图在Lambda内使用任何外部变量都是错误的. ``` // Example program #include <iostream> #include <string> int main() { std::string name = "World!"; auto flag = [](int a, int b) ->bool {return a < b;}; bool ok = false; ok = flag(2, 3); std::cout << "Hello, " << name << "flag:"<< ok <<"!\n"; return 0; } ``` OutPut: ``` Hello, World!flag:1! ``` ![image.png](https://upload-images.jianshu.io/upload_images/4698491-696c996c615750d3.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240) 2). [x, &y] //x 按值捕获, y 按引用捕获. ![image.png](https://upload-images.jianshu.io/upload_images/4698491-96be9968d8072745.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240) 3). [&] //用到的任何外部变量都隐式按引用捕获 ![image.png](https://upload-images.jianshu.io/upload_images/4698491-20534fd9c6d591da.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240) 4). [=] //用到的任何外部变量都隐式按值捕获 ![image.png](https://upload-images.jianshu.io/upload_images/4698491-e0913440d909c7e2.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240) a,b可以在lambda表达式里面读取,但是不可以更改数值。 5). [&, x] //x显式地按值捕获. 其它变量按引用捕获 ![image.png](https://upload-images.jianshu.io/upload_images/4698491-2b8c3bd6fefd8d4e.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240) 6). [=, &z] //z按引用捕获. 其它变量按值捕获 ![image.png](https://upload-images.jianshu.io/upload_images/4698491-fc418449b7511800.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240) ___ 欢迎关注微信号 ![微信.png](https://upload-images.jianshu.io/upload_images/4698491-2d0db1341e2edcea.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)

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

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

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