Передача буфера длиной от 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()
всякий раз, когда / если основной читатель возвращает отрицательные числа, так что у вас нет беспокоиться об этом.
Вы попробовали ActiveMQ? Это упоминает поддержку PHP по Затоптать протоколу. Детали доступны на activemq сайте.
Я вытащил большой пробег из подхода базы данных Ваше описание, хотя, таким образом, я не волновался бы слишком много об этом.
Zend_Framework имеет класс очереди, со многими реализациями Mysql-поддерживаемых, SQS и некоторых других бэкендов.
Лично, у меня были превосходные результаты с BeanstalkD недавно, который также имеет клиент PHP. Я просто сериализирую некоторые данные с JSON для броска в него, который декодируется и работает на рабочем (рабочих).
Вы имеете полный контроль над сервером?
Очередь MySQL могла быть в порядке в таком случае. Имейте Сценарий PHP, который работает постоянно (в бесконечном цикле с условием продолжения), запрашивая базу данных MySQL для новых "задач" и сна () луг, промежуточный для сокращения загрузки во время простоя.
Когда каждая задача будет выполнена, отметьте ее в базе данных и переместитесь в следующую.
Для предотвращения той целой вещи остановки, если сценарий отказывает/существует (переполнение памяти PHP и т.д.), можно, например, поместить его в inittab (если Вы используете Linux в качестве сервера), и init перезапустит его автоматически.