📚 Readers и Writers в Go
В Go входные и выходные данные обрабатываются через универсальные интерфейсы Reader и Writer. Эти интерфейсы позволяют читать и записывать данные из различных источников: файлов, сетевых соединений, буферов, строк и многого другого.
📌 Reader и Writer --- что это?
Go предоставляет два ключевых интерфейса:
Reader
type Reader interface {
Read(p []byte) (n int, err error)
}
Writer
type Writer interface {
Write(p []byte) (n int, err error)
}
Они определяют минимальный набор поведения для чтения и записи данных.
Reader --- читает данные в предоставленный буфер. Writer --- записывает данные из буфера.
🧠 Как работает Reader
При каждом вызове:
Read()заполняет предоставленный буферpбайтами,- возвращает количество прочитанных байт
n, - возвращает ошибку
io.EOF, когда данные закончились.
Пример чтения блоками:
reader := strings.NewReader("SAMPLE")
var result strings.Builder
buffer := make([]byte, 4)
for {
n, err := reader.Read(buffer)
chunk := buffer[:n]
result.Write(chunk)
fmt.Printf("Read %v bytes: %c
", n, chunk)
if err == io.EOF {
break
}
}
fmt.Println(result.String())
🧱 Пошаговое объяснение примера
В примере ниже строка "SAMPLE" читается частями размером 4 байта:
Итерация Прочитано Байты Результат
1 4 S A M P SAMP
2 2 L E SAMPLE
3 0 [] завершено
Так работает чтение блоками --- Reader читает ровно столько, сколько помещается в буфер.
📝 Writer
Writer во многом симметричен Reader:
- получает буфер байтов,
- записывает его содержимое,
- возвращает количество записанных байт.
Пример:
writer := &strings.Builder{}
writer.Write([]byte("Go!"))
fmt.Println(writer.String()) // Go!
⚙️ Буферизация с помощью bufio
Go предоставляет пакет bufio, который реализует буферизированные
Reader и Writer.
Преимущества:
- меньше обращений к реальному источнику данных,
- выше производительность,
- удобные методы, такие как
ReadString,ReadBytes,WriteString.
Пример:
r := bufio.NewReader(os.Stdin)
line, _ := r.ReadString('
')
fmt.Println("You entered:", line)
🧾 Сканирование текста --- bufio.Scanner
Scanner автоматизирует разбор входных данных на части:
- построчно,
- по словам,
- по кастомному разделителю.
Пример чтения строк:
scanner := bufio.NewScanner(os.Stdin)
lines := []string{}
for scanner.Scan() {
lines = append(lines, scanner.Text())
}
if scanner.Err() != nil {
fmt.Println(scanner.Err())
}
fmt.Printf("Line count: %v
", len(lines))
for _, line := range lines {
fmt.Println("Line:", line)
}
📘 Итоги
- Reader и Writer - универсальные интерфейсы для чтения и записи данных.
- Reader заполняет буфер байтами, Writer записывает байты из буфера.
- Через буферы можно читать данные частями.
- Пакет
bufioпредоставляет улучшенные, буферизированные версии. bufio.Scannerидеально подходит для разбора текстовых потоков.