长期运行的副本bytes.Buffer
我有一个长期生活io.Reader
返回每隔几秒钟(从来没有EOF)的一些数据,并做了io.Copy
从读者到bytes.Buffer
一个够程(也永远不会终止)。像这样的东西:长期运行的副本bytes.Buffer
var src io.Reader var buf bytes.Buffer
func main() {
go io.Copy(&buf, src)
// Do stuff. Read from the buffer periodically.
}
我不明白的是,我看到奇怪的结果,当我试图从该缓冲区读取。无论我是否拨打buf.Bytes()
或ioutil.ReadAll(&buf)
或任何其他内容,我只会看到第一个字节反复写入缓冲区。
https://play.golang.org/p/yn0JPrvohV
我的问题是,我究竟做错了什么?我可以以这种方式使用bytes.Buffer
(io.Copy
并定期阅读)吗?
回答:
您无法将您的读取调用与bytes.Buffer
中发生的写入同步到io.Copy
中。即使您将bytes.Buffer
包装在结构中以锁定读/写方法,当Copy等待写入时ReadAll在Read上被阻塞时,您也会发生死锁。您需要手动执行复制,并正确序列化所有访问,或将读写分隔为io.Pipe
。
如果您使用FIFO(io.Pipe
)来同步读取和写入,则不需要任何额外的锁定或通道来追踪第一个io.Reader
。这里有一个例子read
功能,要么打印时它的缓冲区已满,或等待自上次print语句一些间隔:
func read(r io.Reader) { buf := make([]byte, 1024)
pos := 0
lastPrint := time.Now()
for {
n, err := r.Read(buf[pos:])
if n > 0 {
pos += n
}
if pos >= len(buf) || time.Since(lastPrint) > 125*time.Millisecond && pos > 0 {
fmt.Println("read:", buf[:pos])
lastPrint = time.Now()
pos = 0
}
if err != nil {
fmt.Println(err)
break
}
}
if pos > 0 {
fmt.Println("read:", buf[:pos])
}
}
func main() {
pr, pw := io.Pipe()
go func() {
io.Copy(pw, &trickle{})
pw.Close()
}()
read(pr)
}
https://play.golang.org/p/8NeV3v0LOU
以上是 长期运行的副本bytes.Buffer 的全部内容, 来源链接: utcz.com/qa/261579.html