Расовые условия в 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
- таким образом, другой конец, должно быть, прочитал все, что было, чтобы прочитать.