пятница, 15 мая 2020 г.

Как использовать интерфейс io.Reader в Golang

Интерфейс io.Reader представляет сущность, из которой вы можете прочитать поток байтов.

type Reader interface {
    Read(buf []byte) (n int, err error)
}

Read читает до len(buf) байтов в buf и возвращает количество прочитанных байтов - он возвращает ошибку io.EOF, когда заканчивается поток.

Стандартная библиотека предоставляет множество реализаций Reader (включая байтовые буферы в памяти, файлы и сетевые подключения), и Readers принимаются в качестве входных данных многими утилитами (включая реализации HTTP клиента и сервера).

Используйте встроенный ридер

Например, вы можете создать Reader из строки, используя функцию strings.Reader, а затем передать Reader непосредственно в функцию http.Post в пакете net/http. Затем Reader используется в качестве источника данных для POST запроса.

r := strings.NewReader("my request")
resp, err := http.Post("http://foo.bar",
 "application/x-www-form-urlencoded", r)

Поскольку http.Post использует Reader вместо []byte, тривиально, например, использовать вместо него содержимое файла.

Читайте прямо из потока байтов

Вы можете использовать функцию Read напрямую (это наименее распространенный вариант использования).

r := strings.NewReader("abcde")

buf := make([]byte, 4)
for {
    n, err := r.Read(buf)
    fmt.Println(n, err, buf[:n])
    if err == io.EOF {
        break
    }
}

4 <nil> [97 98 99 100]
1 <nil> [101]
0 EOF []

Используйте io.ReadFull для считывания ровно len(buf) байтов в buf:

r := strings.NewReader("abcde")

buf := make([]byte, 4)
if _, err := io.ReadFull(r, buf); err != nil {
    log.Fatal(err)
}
fmt.Println(buf)

if _, err := io.ReadFull(r, buf); err != nil {
    fmt.Println(err)
}

[97 98 99 100]
unexpected EOF

Используйте ioutil.ReadAll, чтобы прочитать все:

r := strings.NewReader("abcde")

buf, err := ioutil.ReadAll(r)
if err != nil {
    log.Fatal(err)
}
fmt.Println(buf)

[97 98 99 100 101]

Буферизированное чтение и сканирование

Типы bufio.Reader и bufio.Scanner обертывают Reader, создавая другой Reader, который также реализует интерфейс, но обеспечивает буферизацию и некоторую помощь для ввода текста.

В этом примере мы используем bufio.Scanner для подсчета количества слов в тексте.

const input = `Beware of bugs in the above code;
I have only proved it correct, not tried it.`

scanner := bufio.NewScanner(strings.NewReader(input))
// Настройка функции разделения.
scanner.Split(bufio.ScanWords) 

count := 0
for scanner.Scan() {
    count++
}
if err := scanner.Err(); err != nil {
    fmt.Println(err)
}
fmt.Println(count)

16


Читайте также:


Комментариев нет:

Отправить комментарий