io.Pipe 中的竞争条件?

Race conditions in io.Pipe?

我有一个函数,它 returns 一个 io.PipeReader 端,并启动一个将数据写入它的 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 匹配 - 所以另一端必须读取所有要读取的内容。