请考虑以下脚本: 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等),但输入扫描器是一个单独的线程,所以我试图让它尽快分割线。