Расовые условия в io.Pipe?

У меня есть функция, которая возвращает Reader конец io.Pipe и запускает подпрограмму, которая записывает данные в Writer конец, а затем закрывает трубу.

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 меня немного волнуют:

func Pipe () (* PipeReader, * PipeWriter)

Труба создает синхронную трубу в памяти. [...] Чтения на одном конце сопоставляются с записями на другом, [...] нет внутренней буферизации.

func (w * PipeWriter) Ошибка CloseWithError(ошибка err)

CloseWithError закрывает средство записи; последующие операции чтения из половины канала чтения не будут возвращать байтов и ошибки с ошибкой, или EOF, если ошибка равна нулю.

То, что я хочу знать, каковы возможные условия гонки здесь? Возможно ли, что моя подпрограмма запишет кучу данных, а затем закроет канал, прежде чем я смогу прочитать все это?

Нужно ли использовать канал для сигнализации о том, когда закрывать? Что может пойти не так, в принципе.

1 ответ

Решение

Нет, гоночных условий нет. Как упоминается в документации, чтения на одном конце сопоставляются с записями на другом. Так когда CloseWithError() достигается, это означает, что каждый Write успешно завершено и сопоставлено с соответствующим Read - таким образом, другой конец, должно быть, прочитал все, что было, чтобы прочитать.

Другие вопросы по тегам