大家好,我是炸鱼。六一前夕在炸鱼的时候,看到一个很神奇的Go2技术方案,想加入更简单、更轻量的匿名函数语法。今天就和大家一起来看看炸鱼吧。NewProposal新的Go提案的目的是增加一种轻量级的匿名函数语法,业界也称为“箭头语法”。它是由@DamienNeil提出的。提案的出处是《proposal: Go 2: Lightweight anonymous function syntax[1]》,正反两面:wetoexpand。下面的例子:import("fmt""math")funccompute(fnfunc(float64,float64)float64)float64{returnfn(3,4)}funcmain(){hypot:=func(x,yfloat64)float64{returnmath.Sqrt(x*x+y*y)}fmt.Println(hypot(5,12))fmt.Println(compute(hypot))fmt.Println(compute(math.Pow))}以上代码主要是实现了多个匿名闭包函数,其实业务逻辑上什么都没有。相信由于闭包签名的复杂性,代码可读性不高。为了避免这种情况,许多语言允许省略匿名函数的参数和返回类型,因为它们可能是从上下文中派生出来的,可以直接重用。这是Scala中的一个示例:compute((x:Double,y:Double)=>x+y)compute((x,y)=>x+y)//参数类型elided.compute(_+_)//或者更短。Rust示例:compute(|x:f64,y:f64|->f64{x+y})compute(|x,y|{x+y})//省略参数和返回类型。所以这个Go的提议就是在匿名闭包中加入这种轻量级的语法,让代码看起来更简洁,提高代码的可读性。PHP示例:$x=1;$fn=fn()=>$x++;//不影响x的值$fn();var_export($x);//输出1更有趣。真实案例Cap'nProtoGo开源库Cap'nProto(capnproto/go-capnproto2[2])是一种极速数据交换格式,类似于ProtocolBuffers,但速度要快得多。下面是它的代码使用片段:s.Write(ctx,func(phashes.Hash_write_Params)error{err:=p.SetData([]byte("Hello,"))returnerr})假设我们是Rust,效果如下::s.Write(ctx,|p|{err:=p.SetData([]byte("Hello,"))returnerr})errgroup这个errgroup库相信大家都不陌生,在场景中常用于异步多goroutine的err处理和同步。下面是它的一个使用片段:g.Go(func()error{//performworkreturnnil})假设我们是Scala,效果如下:g.Go(()=>{//performworkreturnnil})onlyfrom比较码数,只比较码数确实更简单。讨论这个提案在社区引起了不小的轰动和讨论,有很多不同的观点。语法格式首先从Go的语法角度来看。语法格式为:[标识符]|"("IdentifierList")""=>"ExpressionList示例将变为:s.Write(ctx,p=>p.SetData([]byte("Hello,"))g.Go(=>nil)更短并且更短。降低了可读性。很多朋友认为这样降低了代码的可读性,更难理解。得在脑子里转换几下才知道是什么意思。。。想一想,赶上了公司的一条炸鱼。假设他事先不知道语法,他能看懂这段代码的意思吗?如下:g.Go(=>nil)显然,他不能100%确定。但是如果没有这个语法,它只是一个普通的匿名闭包,可以阅读。因为语法基本上是常识,而箭头语法不是。早期设计在Go的早期设计中被拒绝了,实际上是“箭头语法”,也就是这个提案,已经研究过了。当时的语法是:funcf(xint)->float32因为它没有很好地处理多个(非元组)返回值;一旦func和parameters出现,箭头就是多余的并且会变得复杂。虽然这样做看起来会更“漂亮”,但“漂亮”(从数学上看)可能仍然是多余的。它看起来也属于“不同”语言的语法。官方还认为必须非常小心,不要为闭包创建特殊语法。因为现在Go拥有的是简单而规则的语法和逻辑。最终放弃了加箭头语法的想法。替换为省略号从代码示例来看,主要是类型声明和结构导致了复杂性。因此,也有人提出用省略号来达到类似的效果。如下代码:s.Write(ctx,func(p_)_{returnp.SetData([]byte("Hello,"))})这样做的好处是不需要修改语法。总结提案作者的初衷,可能是需要让匿名闭包更加简洁,降低代码的复杂度。但实际上,从本质上讲,节省的只是表面上的复杂性。一旦引入这种“箭头”语法,可能会更加加重脑转换的开销。看代码的时候,你要脑补,会增加底下的脑力开销。当然,我也可能是错的。你怎么认为?是否支持Go新加入的轻量级匿名闭包语法,也就是业界俗称的“箭头”语法。参考文献[1]proposal:Go2:Lightweightanonymousfunctionsyntax:https://github.com/golang/go/issues/21498[2]capnproto/go-capnproto2:https://github.com/capnproto/go-capnproto2
