Передача буфера длиной от 1 до bufio.Read
, , когда для считывателя поддерживается базовый os.File , действительно вернет n==0, io.EOF
, если файл находится в EOF.
Документация немного неточна, потому что некоторые действия зависят от основного читателя, который вы передаете читателю bufio
.Код для bufio.Read()
рисует более точную картину.Я обрисую логику.
bufio.Read
: Выдает Read
только базовому считывателю, если все байты во внутреннем буфере исчерпаны.Итак, по-видимому, если вы уже прочитали столько байтов из буферизованного считывателя, сколько байтов в базовом файле, этот внутренний буфер должен быть исчерпан при последнем вызове bufio.Read(buf[0:1])
для проверки EOF.
Когда внутренний буфер исчерпан, и вы запрашиваете у читателя bufio
больше, bufio.Read
выполнит не более один вызов основного читателя.Тип ошибки, которую вы получите, будет зависеть от вашего основного читателя.
Запрос на чтение n > 0
байтов из os.File
, когда указатель чтения уже находится в EOF, должен вернуть 0, io.EOF
(в соответствии сДокумент о os.File File.Read
).Но если ваш базовый читатель был чем-то другим, возможно, пользовательским типом, специфичным для вашего приложения, предназначенным для возврата 0, nil
в EOF, тогда bufio.Read
вернет это вместо этого.
bufio.ReadByte
: Логика bufio.ReadByte
немного отличается, но результат должен быть таким же, как bufio.Read
в тех случаях, когда основной читатель - os.File
.Основное отличие от bufio.Read
состоит в том, что bufio.ReadByte
может сделать несколько попыток пополнить внутренний буфер.Если во время повторного заполнения обнаружена ошибка (которая будет иметь место для считывателя os.File
в EOF), она возвращается после первой ошибочной попытки чтения.Итак, если ваш базовый Reader является os.File
читателем, то вы получите 0, io.EOF
тогда и только тогда, когда ваш базовый файл находится в EOF.Если ваш базовый считыватель был пользовательским типом считывателя, который вернул 0, nil
только в EOF, то bufio.ReadByte
в конечном итоге выдаст ошибку «NoProgress».Я не уверен, почему логика повторения используется только в bufio.ReadByte
, но хорошая новость заключается в том, что любой из вариантов можно использовать, если ваш базовый файл ведет себя как os.File
.
Другая информация:
Это не относится напрямую к golang, но вам может быть интересен следующий поток: Может читать (2), возвращать ноль байтов, когда не в EOF .Его тема - семантика системного вызова read () (POSIX).Чтение неблокирующих сокетов / файлов, даже когда данные не готовы, должно возвращать -1, а не 0, и устанавливать errno EAGAIN (или EINTR при прерывании).Неблокирующие сокеты / файлы на самом деле не являются родной концепцией (насколько я знаю), и модуль bufio
, в частности, будет panic()
всякий раз, когда основной читатель возвращает отрицательные числа, поэтому у вас нетбеспокоиться об этом.