io.Pipe 中的竞争条件?
Race conditions in io.Pipe?
我有一个函数,它 returns 一个 io.Pipe
的 Reader
端,并启动一个将数据写入它的 Writer
端的 go-routine,然后关闭管道。
func GetPipeReader() io.ReadCloser {
r, w := io.Pipe()
go func() {
_, err := io.CopyN(w, SomeReaderOfSize(N), N)
w.CloseWithError(err)
}()
return r
}
func main() {
var buf bytes.Buffer
io.Copy(&buf, GetPipeReader())
println("got", buf.Len(), "bytes")
}
https://play.golang.org/p/OAijIwmtRr
这似乎在我的测试中总是有效,因为我得到了我写的所有数据。但是 API docs 让我有点担心:
func Pipe() (*PipeReader, *PipeWriter)
Pipe creates a synchronous in-memory pipe. [...] Reads on one end are
matched with writes on the other, [...] there is no internal
buffering.
func (w *PipeWriter) CloseWithError(err error) error
CloseWithError closes the writer; subsequent reads from the read half
of the pipe will return no bytes and the error err, or EOF if err is
nil.
我想知道的是,这里可能的竞争条件是什么?我的 go-routine 会写入一堆数据,然后在我读取所有数据之前关闭管道,这是否合理?
我是否需要使用通道来发出关闭时间的信号?基本上可以出什么问题。
不,没有竞争条件。正如文档中提到的,一端的读取与另一端的写入相匹配。因此,当到达 CloseWithError()
时,这意味着每个 Write
都已成功完成并与相应的 Read
匹配 - 所以另一端必须读取所有要读取的内容。
我有一个函数,它 returns 一个 io.Pipe
的 Reader
端,并启动一个将数据写入它的 Writer
端的 go-routine,然后关闭管道。
func GetPipeReader() io.ReadCloser {
r, w := io.Pipe()
go func() {
_, err := io.CopyN(w, SomeReaderOfSize(N), N)
w.CloseWithError(err)
}()
return r
}
func main() {
var buf bytes.Buffer
io.Copy(&buf, GetPipeReader())
println("got", buf.Len(), "bytes")
}
https://play.golang.org/p/OAijIwmtRr
这似乎在我的测试中总是有效,因为我得到了我写的所有数据。但是 API docs 让我有点担心:
func Pipe() (*PipeReader, *PipeWriter)
Pipe creates a synchronous in-memory pipe. [...] Reads on one end are matched with writes on the other, [...] there is no internal buffering.
func (w *PipeWriter) CloseWithError(err error) error
CloseWithError closes the writer; subsequent reads from the read half of the pipe will return no bytes and the error err, or EOF if err is nil.
我想知道的是,这里可能的竞争条件是什么?我的 go-routine 会写入一堆数据,然后在我读取所有数据之前关闭管道,这是否合理?
我是否需要使用通道来发出关闭时间的信号?基本上可以出什么问题。
不,没有竞争条件。正如文档中提到的,一端的读取与另一端的写入相匹配。因此,当到达 CloseWithError()
时,这意味着每个 Write
都已成功完成并与相应的 Read
匹配 - 所以另一端必须读取所有要读取的内容。