首页 > 解决方案 > 如何将 io.Reader 拆分为具有相同行数的多个 io.Reader?

问题描述

我想在 Go 中做同样的事情,就像在这里问的那样。

我正在解析一个巨大的日志文件,我需要逐行解析它。在每一行上,我将行反序列化为一个结构。数据可能来自任何数据源(文件、网络等)。io.Reader所以,我在我的函数中收到了一个。由于文件很大,我想将它拆分到许多 goroutine 中。

我可以使用io.Pipeetc 轻松完成此操作。但是,我需要在不切割线条的情况下拆分文件,例如,将它们分成两半而不在中间切割它们。这样,每个 goroutine 可能会收到一个io.Reader,然后它们可能会在文件的不同部分工作。

有时,我还需要发送io.MultiReader到我的函数。在那种情况下,我会再次这样做。所以,它不一定是同一个文件(但大部分是)。

func scan(r io.Reader, pf ProcessFunc) {
    // need to split `r` here if `r` is:
    // r.(io.ReadSeeker)

    // run goroutine #1 with 50% of the stream
    // uses bufio.Scanner

    // run goroutine #2 with 50% of the stream
    // uses bufio.Scanner

    // another goroutine is receiving the deserialized values
    // and sends them to the ProcessFunc for processing further
    // down the pipeline
}

假设数据是这样的:

foo1 bar2
foo3 bar4
foo5 bar6
foo7 bar8

goroutine #1 将获得一个 io.Reader ,如下所示:

foo1 bar2
foo3 bar4

goroutine #2 会得到一个 io.Reader ,如下所示:

foo5 bar6
foo7 bar8

但不是这样:

o5 bar6    -> breaks the line in the second io.Reader
foo7 bar8

标签: go

解决方案


你有几个选择:

  1. 如果您有可搜索的数据,您可以搜索然后扫描下一个换行符,这样您就可以确保只在换行符处拆分

  2. 将行传递给 goroutine 而不是 io.readers。基本上,每个 goroutine 都会有一个通道,主路由会将 io.reader 中的每一行输入到通道中。

  3. 事先用类似的东西拆分文件split


推荐阅读