来自python背景,刚开始使用Go,我发现自己在寻找与Go中的map()和reduce()函数等效的函数。我没有找到他们,所以我又回到了原地。例如,这是我用来代替map()的,其中mapFunction在其他地方定义:
data := make([]byte, 1024)
count, err := input.Read(data) // error handling removed from this snippet
for i:=0; i<count; i++ {
data[i] = mapFunction(data[i])
}
,这是我使用的,而不是减少(),其中有两个状态变量,我用来跟踪引号字段在CSV中,因为代码移动通过切片中的每个项目:
data := make([]byte, 1024)
count, err := input.Read(data) // error handling removed from this snippet
for i:=0; i<count; i++ {
data[i], stateVariable1, stateVariable2 =
reduceFunction(data[i], stateVariable1, stateVariable2)
}
以下是我的问题:
- 是否有我错过的内置功能?
- 是否适合使用这些可变片?
- 使用map()的例程是个好主意吗?这是否允许读取文件的IO操作与在每个项目上运行映射函数的进程解耦,从而允许并行化?
- 是否说例程不适合reduce()函数,因为这两个状态变量是由前面所有的数据定义的,它必须顺序进行。换句话说,这个顺序进程不能从并发架构中获益?
谢谢!
ps -完整的代码在这里:https://github.com/dbro/csvquote/blob/go/csvquote.go
总之:
- 没有,没有内置map或reduce。
- 是的。还有什么?
- 。如果没有事先测量或证明有实际需要,甚至不要考虑这些东西。
- 是的。
稍微长一点。
- Go没有功能,没有map/reduce内置或在标准库 在Go中有数组和切片。两者都是可变的。切片是大多数时候的自然选择。
- 过早优化……但是当然:读取一个处理可以进入一个循环,并在bufio中包装输入。阅读器是个好主意。
- 例程很好,它们允许不同类型的程序构造,但这并不意味着它们可以用于所有事情。没有必要通过引入go例程来使一个非常清晰的for循环复杂化。
Volker给出了一个很好的答案,但它没有发挥Go的主要优势之一,即它的并发性。map/reduce类型的操作可以通过使用"服务器场"策略并行化(不考虑过早的优化)。这涉及到将要完成的工作分成工作包,这些工作包被发送给不同的工人(即程序)。Map/Reduce是一种通用的方法,需要更高阶的函数和不可变的数据结构。
尽管Go不是函数式语言,但它足够灵活,允许定制并行分解。虽然没有不可变性,但它允许通过使用复制语义来避免混叠,从而消除了在运行例程之间交换值时的竞争条件,这实际上是一样好的。简单地说:在共享时直接使用结构体而不是指向结构体的指针。(为了提供帮助,Go1.1中有一个新的种族检测器)。 服务器群模式是实现高并行化效率的好方法,因为它是自平衡的。这与几何分解(即通过聚集区域共享数据网格并将其分配给处理器)和算法分解(即将管道中的不同阶段分配给不同的处理器)形成对比,两者都可能受到负载不平衡的影响。围棋能够表达这三种。