Ответ 1
Ваш код неэффективен. Он каждый раз выделяет и инициализирует data
через цикл.
for {
data := make([]byte, 4<<20) // Read 4MB at a time
}
Код для reader
как io.Reader
неверен. Например, вы игнорируете количество байтов, считанных с помощью _, err := reader.Read(data)
, и вы неправильно обрабатываете ошибки err
.
import "io"
type Reader interface { Read(p []byte) (n int, err error) }
Reader - это интерфейс, который обертывает базовый метод чтения.
Чтение считывает до len (p) байтов в p. Он возвращает количество байтов read (0 <= n <= len (p)) и любая возникшая ошибка. Даже если Read возвращает n < len (p), он может использовать все p как место для царапин во время вызов. Если доступны некоторые данные, но не len (p) байты, Read условно возвращает то, что доступно, а не ждет больше.
Когда Read обнаруживает ошибку или состояние конца файла после успешно считывая n > 0 байтов, он возвращает количество прочитанных байтов. Он может возвращать (не-ноль) ошибку из одного и того же вызова или возвращать error (и n == 0) из последующего вызова. Экземпляр этого общего Дело в том, что читатель возвращает ненулевое число байтов в конце входного потока может возвращать либо err == EOF, либо err == nil. next Read должен возвращать 0, EOF независимо.
Звонящие должны всегда обрабатывать n > 0 байт, возвращенных до учитывая ошибку err. Это правильно обрабатывает ошибки ввода-вывода, которые происходят после прочтения некоторых байтов, а также обоих разрешенных EOF поведения.
Реализации Read не рекомендуется возвращать нулевой байт count с ошибкой nil, за исключением случаев, когда len (p) == 0. Звонящие должны лечить возврат 0 и ноль, указывающий на то, что ничего не произошло; в в частности, это не указывает на EOF.
Реализации не должны сохраняться.
Здесь программа чтения файла модели, соответствующая интерфейсу io.Reader
:
package main
import (
"bufio"
"io"
"log"
"os"
)
func main() {
nBytes, nChunks := int64(0), int64(0)
r := bufio.NewReader(os.Stdin)
buf := make([]byte, 0, 4*1024)
for {
n, err := r.Read(buf[:cap(buf)])
buf = buf[:n]
if n == 0 {
if err == nil {
continue
}
if err == io.EOF {
break
}
log.Fatal(err)
}
nChunks++
nBytes += int64(len(buf))
// process buf
if err != nil && err != io.EOF {
log.Fatal(err)
}
}
log.Println("Bytes:", nBytes, "Chunks:", nChunks)
}
Вывод:
2014/11/29 10:00:05 Bytes: 5589891 Chunks: 1365