Урок объясняет, как работают интерфейсы io.Reader и io.Writer в Go, как читать и записывать данные блоками, зачем нужны буферизированные обёртки из bufio, и как использовать bufio.Scanner для удобной обработки текстового ввода.
В Go входные и выходные данные обрабатываются через универсальные интерфейсы Reader и Writer. Эти интерфейсы позволяют читать и записывать данные из различных источников: файлов, сетевых соединений, буферов, строк и многого другого.
Go предоставляет два ключевых интерфейса:
type Reader interface {
Read(p []byte) (n int, err error)
}
type Writer interface {
Write(p []byte) (n int, err error)
}
Они определяют минимальный набор поведения для чтения и записи данных.
Reader --- читает данные в предоставленный буфер. Writer --- записывает данные из буфера.
При каждом вызове:
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 во многом симметричен Reader:
Пример:
writer := &strings.Builder{}
writer.Write([]byte("Go!"))
fmt.Println(writer.String()) // Go!
Go предоставляет пакет bufio, который реализует буферизированные
Reader и Writer.
Преимущества:
ReadString, ReadBytes, WriteString.Пример:
r := bufio.NewReader(os.Stdin)
line, _ := r.ReadString('
')
fmt.Println("You entered:", line)
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)
}
bufio предоставляет улучшенные, буферизированные версии.bufio.Scanner идеально подходит для разбора текстовых потоков.