将Scanner.Bytes()提供给Go中的通道

时间:2018-05-07 22:27:46

标签: go concurrency

请考虑以下脚本: https://play.golang.org/p/o4ZhuB3GJ0s(下面重要部分)

它创建的随机(ish)字符串看起来像" foo | foo" (其中" foo"是随机的,但重复)。

我用Scanner.Bytes()将它们读入输入通道,然后16个工作线程将它们转换为字符串并将它们放入输出通道。

在输出通道中,我将字符串拆分为|以确保双方都相同(没有数据损坏)。

这是扫描输入缓冲区的代码部分:

// Send input into channel
go func() {
    // Normally os.Stdin
    s := bufio.NewScanner(simulatedStdin)
    start = time.Now()
    for s.Scan() {
        thisLine := s.Bytes()
        line := make([]byte, len(thisLine))
        // Copy the slice so it's not changed on the next iteration
        copy(line, thisLine)
        lines <- line

        // Works, but perhaps the least efficient way to do it
        // lines <- []byte(string(s.Bytes()))
        // lines <- []byte(s.Text())

        // Fails
        // lines <- []byte(s.Bytes())
        // lines <- s.Bytes()[:]
        // lines <- s.Bytes()
    }
    close(lines)
}()

上面的版本工作正常,但是如果我只做lines <- s.Bytes()(或我测试过的其他版本),数据会被破坏,因为Scanner.Bytes()总是返回相同的切片,而且我&#39;将那片切片穿过通道,但是当工人正在读它时它会发生变异。

我的问题是,将Scanner.Bytes()置于通道上以防止此损坏的正确/惯用方法是什么?我上面发布的方式有效,但它相当丑陋恕我直言,字符串黑客很短,但它真的是一种复制数据的可怕方式。

最终,我使用这种方法来读取数十亿行数据,因此如果可以删除额外的[]byte副本,我就可以了。在工作人员中完成的工作很慢(JSON Unmarshaling等),但输入扫描器是一个单独的线程,所以我试图让它尽快分割线。

0 个答案:

没有答案