左耳听风_112_111_Go_编程模式Map-Reduce
你好,我是沈浩网名做尔的house.这节课呢我们来学习一下函数式编程中啊非常重要的map, reduce和filter这三种操作。
这三种操作呢可以让我们轻松灵活的进行一些数据处理。
毕竟呢我们的程序啊在大多数情况下都在倒腾数据,尤其是对于一些需要统计的业务场景来说啊,map reduce和filter是非常通用的玩法。
那话不多说,我们先来看几个例子。
首先呢是一个map示例。
在文中的程序代码中呢,我写了两个map函数。
这两个函数呢需要两个参数。
呃,一个参数呢是字符串,数组,说明需要处理的数据呢是一个字符串。
而另一个参数呢是一个函数,函数的入参呢是一个字符串,而返回值呢是一个字符串或者整形整个map函数的运行逻辑呢都很相去。
那函数题呢都是在遍历第一个参数的数组,然后呢调用第二个参数的数数,把它的值呢组合成另一个数组返回出去。
这样呢我们就可以向文中这种方式啊来使用这两个函数的。
可以看到我们给第一mamap strreen to string呢传了一个功能,是转大写的函数,于是出来的数组啊就成了全大写的。
而map string to int呢传的是计算长度,所以出来的数组呢是每一个字符串的长度。
那除了map以外啊,还有reduce和filter.这两个函数的示例呢,我都放到了文稿里,你记得要看一下。
那为了方便你理解呢,我在文中啊给你展示了一张图,它形象的说明了map和reduce的业务语义,在数据处理中呢非常有用。
那通过刚刚那些事例呢,你现在啊应该有点明白了,map reduce和filter呢只是一种控制逻辑。
而真正的业务逻辑呢是以传给他们的数据和函数来定义的。
是的,这是一个很经典的业务逻辑和控制逻辑,分离解耦的编程模式。
那接下来呢我在文中啊展示了一个有业务意义的代码示例,来进一步帮助你理解什么叫控制逻辑与业务逻辑分离。
我呢构造了一组员工信息,通过reduce和filter啊来统计有多少员工大于四十岁,有多少的员工薪水大于六千,还有其他各种自定义的统计视例。
那课后呢你可以点开文章看一看。
那接着呢我们再来说一说泛型的map和reduce.在刚刚员工信息统计的例子中啊,因为要处理的数据的类型不同,我们呢就需要写出不同版本的mac reduce.但是呢他们的代码看上去都是类似的,所以呢这里啊就要提到泛性编程了。
先来说简单版的generary map.我在写这节课的时候呢,购物园它还不只是范省。
所以目前的构语言的泛型呢只能用interface加上reflect来完成。
那interface呢可以理解成c里面的worid的星和java中的object,而reflex呢是go的反射机制。
包作用呢是在运行时的检查类型。
那一个非常简单的不做任何类型检查的泛型的map函数应该怎么写呢?你可以看一下文稿中的代码,我来简单解释一下这段代码。
首先呢我们通过reflect点value off获得interface的值。
那其中一个呢是数据v data,另一个呢是函数VFN.然后呢,我通过VFN点call方法去调用函数,通过reflect取v data的value啊,获得数据构语言里面啊反射的语法有点令人费解。
不过呢简单看一下手册还是能够读懂的反射啊,不是这节课的重点我就不讲了。
那如果你还不太懂这些基础知识呢,课下可以学习一下相关的教程。
总之呢我们可以有一组代码,让不同类型的数据呢可以使用相同的逻辑的map.但是呢因为反射是运行时的事儿,所呢如果果类型出问题的话,就会有运行时的错误。
比如说文章里这一行代码呢可以很轻松的便于通过。
但是呢在运行时啊却出问题了,而且呢还是拍那个错误。
那如果要写一个健壮的程序呢,对于这种用interface的过度泛型啊,我们就需要自己来做类型检查。
那文中呢有一个类型检查的map代码,你会发现代码呢一下子就复杂起来了。
可见复杂的代码都是在处理异常的地方。
我这里呢不不算算work through所有代码,别看代码多啊,还是可以读懂的。
我这里呢主要列一下代码中的几个要点。
第一,在代码中呢我没有使用map函数,因为它和数据结构啊有含义冲突的问题。
所以呢我使用了transform这个来源于c加加STL中的命名。
第二,这里呢有两个版本的函数,一个呢是返回一个全新的数组transform,一个呢是就地完成transform in place.第三,在主函数中呢,我用了kind的方法来检查数据类型,是不是slice函数类型,是不是funk.第四,检查函数的参数和返回类型呢是通过verify fancsignature方法来完成的。
我用number in函数来检查函数的入参用name out来检查函数的返回值。
最后如果需要新生成一个slice呢,会使用reflect点mix slice来完成。
好了,有了这段代码之后呢,我们的代码就可以很开心的使用了。
它既可以用于字符串数组,又可以用于整形数组,也可以用于结构体。
那除了map以外呢,通过泛醒我们还可以实现健壮版的generic reduce和generic. Filter.我也给出了具体的代码之后呢,你可以去文章里看一下。
最后呢我还有几点想说的。
第一,使用反射来做这些东西呢会有一个问题,那就是代码的性能呢会很差。
所以我在前面讲的代码呢不能用在需要高性能的地方。
那怎么解决这个问题呢?我会在下节课给你介绍一下。
第二,这节课的代码呢,大量的参考roll pad的版本,你可以点击文稿中出的链接呢看一看。
第三,其实在全世界范围之内啊,有大量的程序员都在问,go语言官方什么时候能在标准库中啊支持map或reduce?那rob pack呢就说这种东西难写吗?还需要我们官方来帮你们写吗?这种代码呢,我多少年前就写过了,但是呢我一次都没有用过,我还是喜欢用for循环。
我觉得你最好也跟我一起用for循环。
那我个人觉得map和reduce在数据处理的时候呢,还是很有用的。
Roll pack可能平时也不怎么写业务逻辑的代码,所以呢他可能也不太了解业务的变化有多么频繁。
当然好还是不好,你自己来判断。
但是呢多学一些编程模式啊,一定是对自己很有帮助的。
好了,这节课呢就到这里。
如果你觉得今天的内容啊对你有所帮助,欢迎你帮我分享给更多人。