Реализация собственных средств чтения
Создавайте собственные потоки
«Реализация собственных средств чтения» — бесплатный урок Go Academy на CoddyKit. Это урок 4 из 4. Ты можешь прочитать весь урок бесплатно ниже — а потом практиковать его прямо в браузере с встроенным редактором кода и ИИ-репетитором 24/7. Это часть пути обучения Go Academy, и твой прогресс синхронизируется между веб-версией и приложением CoddyKit. Курс Go Academy содержит 4 уроков всего.
Создание собственных потоков
Вы можете создавать собственные источники данных, реализовав интерфейс io.Reader с единственным методом. После этого ваш тип будет работать с любым вспомогательным средством io.
Реализуемый метод
Реализуйте Read(p []byte) (n int, err error) для своего типа. Заполните p, верните количество байтов и верните io.EOF, когда данные закончатся.
Читатель константного значения
Здесь показан читатель, бесконечно выдающий один и тот же байт, ограниченный с помощью LimitReader.
package main
import (
"fmt"
"io"
)
type constReader struct{ ch byte }
func (c constReader) Read(p []byte) (int, error) {
for i := range p {
p[i] = c.ch
}
return len(p), nil
}
func main() {
r := io.LimitReader(constReader{ch: 'A'}, 5)
data, _ := io.ReadAll(r)
fmt.Println(string(data))
}Сигнализация EOF
Верните io.EOF, когда источник будет исчерпан. Можно вернуть его отдельно или вместе с последними байтами.
package main
import (
"fmt"
"io"
)
type oneShot struct{ done bool }
func (o *oneShot) Read(p []byte) (int, error) {
if o.done {
return 0, io.EOF
}
o.done = true
n := copy(p, []byte("once"))
return n, nil
}
func main() {
data, _ := io.ReadAll(&oneShot{})
fmt.Println(string(data))
}Чтение из среза
Собственный читатель может отслеживать позицию в исходных данных и возвращать при каждом вызове очередную часть.
package main
import (
"fmt"
"io"
)
type sliceReader struct {
data []byte
pos int
}
func (s *sliceReader) Read(p []byte) (int, error) {
if s.pos >= len(s.data) {
return 0, io.EOF
}
n := copy(p, s.data[s.pos:])
s.pos += n
return n, nil
}
func main() {
r := &sliceReader{data: []byte("custom")}
out, _ := io.ReadAll(r)
fmt.Println(string(out))
}Преобразующий читатель
Оберните другой читатель и преобразуйте байты на лету — здесь каждый байт переводится в верхний регистр по мере чтения потока.
package main
import (
"bytes"
"fmt"
"io"
)
type upper struct{ r io.Reader }
func (u upper) Read(p []byte) (int, error) {
n, err := u.r.Read(p)
for i := 0; i < n; i++ {
if p[i] >= 'a' && p[i] <= 'z' {
p[i] -= 32
}
}
return n, err
}
func main() {
out, _ := io.ReadAll(upper{r: bytes.NewReader([]byte("hello"))})
fmt.Println(string(out))
}Учитывайте длину буфера
Никогда не записывайте больше len(p) байтов. Используйте copy(p, src): число копируемых байтов ограничено меньшим из срезов, а затем верните это число.
Получатели-значения и получатели-указатели
Если ваш читатель отслеживает позицию или состояние, используйте получатель-указатель, чтобы изменения сохранялись между вызовами. Для читателей без состояния можно использовать получатель-значение.
Композиция с помощниками io
Поскольку ваш тип соответствует io.Reader, его можно сразу использовать с io.Copy, bufio.NewReader, io.LimitReader и другими средствами.
package main
import (
"io"
"os"
)
type dots struct{ left int }
func (d *dots) Read(p []byte) (int, error) {
if d.left == 0 {
return 0, io.EOF
}
p[0] = '.'
d.left--
return 1, nil
}
func main() {
io.Copy(os.Stdout, &dots{left: 4})
os.Stdout.WriteString("\n")
}Распространённые ошибки
- Забыть вернуть
io.EOF— чтение станет бесконечным - Записать данные за пределами
len(p) - Использовать получатель-значение для читателей с состоянием
Зачем нужны собственные читатели
Они позволяют встроить любой источник — генераторы, декодеры, ограничители скорости, зашифрованные потоки — в универсальную экосистему ввода-вывода Go.
Быстрая проверка
Проверьте свои знания о собственных читателях.
Итоги
Вы научились создавать собственные потоки.
- Реализуйте
Read(p []byte) (int, error) - Используйте
copyи учитывайтеlen(p) - Возвращайте
io.EOF, когда данные закончатся - Для читателей с состоянием используйте получатель-указатель
- Свободно объединяйте их со всеми вспомогательными средствами io
Часто задаваемые вопросы
Урок «Реализация собственных средств чтения» бесплатный?
Да — полный текст урока «Реализация собственных средств чтения» бесплатно доступен здесь в веб-версии. Чтобы практиковать его интерактивно (встроенный редактор кода и ИИ-репетитор 24/7) и разблокировать остальной курс Go Academy, подпишись на CoddyKit PRO. Курс Go Academy содержит 4 уроков всего.
Чему я научусь в уроке «Реализация собственных средств чтения»?
Создавайте собственные потоки Ты практикуешь Go Academy с помощью реального кода, который запускаешь прямо в браузере, и ИИ-репетитор 24/7 отвечает на твои вопросы во время урока.
Нужен ли мне опыт, чтобы начать Go Academy?
Предыдущий опыт не требуется. Go Academy на CoddyKit структурирован для всех уровней — от новичков до продвинутых, поэтому ты можешь начать отсюда или с самого начала и учиться в своем темпе. Это урок 4 из 4.
Сколько времени занимает урок «Реализация собственных средств чтения»?
Большинство уроков CoddyKit занимают около 5–10 минут. Каждый из них компактный и интерактивный, поэтому ты постоянно делаешь прогресс и продолжаешь с того же места в веб-версии и приложении.
Можно ли писать и запускать код в этом уроке Go Academy?
Да. Каждый урок Go Academy включает встроенный редактор кода, поэтому ты пишешь и запускаешь реальный код прямо в браузере и получаешь моментальную обратную связь от AI — локальная установка не требуется.
Все уроки этого курса
- Интерфейс Reader
- Интерфейс Writer
- Вспомогательные функции io
- Реализация собственных средств чтения