Это два базовых интерфейса Go для потоковой обработки данных:
type Reader interface {
Read(p []byte) (n int, err error)
}
type Writer interface {
Write(p []byte) (n int, err error)
}
Всё, что умеет читать — Reader. Всё, что умеет писать — Writer. Файлы, сетевые соединения, буферы, HTTP body — все реализуют эти интерфейсы.
// Копирование из Reader в Writer
src, _ := os.Open("input.txt")
dst, _ := os.Create("output.txt")
io.Copy(dst, src) // потоково, без загрузки всего в память
// Чтение HTTP body
body, _ := io.ReadAll(resp.Body) // []byte
// Строка → Reader
r := strings.NewReader("hello world")
Почему это мощно: функция принимает io.Reader — ей всё равно, откуда данные (файл, сеть, буфер, тест). Композиция через обёртки: io.LimitReader, io.TeeReader, bufio.NewReader.