io.Reader和io.Writer是Go流式I/O核心接口,各仅含Read/Write方法,支持任意数据源复用与组合;常见用法包括io.Copy、bufio缓冲、io.LimitReader和io.MultiWriter等链式处理方式。

Go 语言的 io 包是流式 I/O 的核心,它不关心数据从哪来、到哪去,只关注“怎么读”和“怎么写”。Reader 和 Writer 是两个极简但强大的接口,它们让不同来源(文件、网络、内存、管道等)的数据处理逻辑可以复用、组合、测试。
io.Reader 只有一个方法:Read(p []byte) (n int, err error)。它尝试把最多 len(p) 字节的数据填入切片 p,返回实际读取字节数和错误。只要实现了这个方法,就是合法的 Reader——比如 *os.File、bytes.Reader、strings.Reader、net.Conn 都是。
io.Writer 同样只有一个方法:Write(p []byte) (n int, err error)。它尝试把切片 p 全部写出去,返回实际写入字节数和错误。文件、网络连接、缓冲区、甚至自定义日志器,只要能接收字节流,就能实现 Writer。
关键在于:它们都基于“批处理 + 返回实际数量”的设计,天然支持部分读写、边界处理和错误恢复,不用手动管理 EOF 或缓冲区大小。
立即学习“go语言免费学习笔记(深入)”;
利用 io 接口的统一性,你可以像搭积木一样组合操作:
io.Copy(dst Writer, src Reader) —— 它内部循环调用 Read/Write,自动处理缓冲、EOF 和错误,是最常用也最安全的流转发方式。bufio.NewReader(r io.Reader) 或 bufio.NewWriter(w io.Writer) 包装原始 Reader/Writer,减少系统调用次数,提升小数据频繁读写的性能。io.LimitReader(r io.Reader, n int64) 创建一个只允许读前 n 字节的 Reader,适合防止恶意大文件或截断响应。io.MultiWriter(writers ...io.Writer) 把一份数据同时写进多个目标(如日志同时输出到文件和 stdout)。假设你想读取一段文本,转成大写,再写入目标。不依赖中间字符串或切片,全程流式处理:
type UpperCaseReader struct {
r io.Reader
}
func (u *UpperCaseReader) Read(p []byte) (int, error) {
n, err := u.r.Read(p)
for i := 0; i < n; i++ {
p[i] = bytes.ToUpper([]byte{p[i]})[0]
}
return n, err
}然后这样用:
src := strings.NewReader("hello world")
upper := &UpperCaseReader{r: src}
dst := os.Stdout
io.Copy(dst, upper) // 输出 "HELLO WORLD"注意:这个例子简化了 Unicode 处理(真实场景建议用 strings.ToTitle 配合 bufio.Scanner),但它清晰展示了如何在 Read 过程中做实时转换——无需加载全部内容到内存。
实际开发中,优先使用标准库提供的组合函数(io.Copy, io.CopyN, io.MultiReader 等),而不是自己循环 Read/Write;
处理 HTTP Body、大文件上传下载、日志采集等场景时,始终以 Reader/Writer 为参数设计函数签名,保持可测试性和可替换性;
遇到需要解析结构化数据(JSON/XML)时,直接传入 io.Reader 给 json.NewDecoder(r).Decode(&v),它会按需读取,不会一次性加载全文;
调试流问题时,可用 io.TeeReader(r, w io.Writer) 在读取的同时镜像写入日志,方便排查数据流向。
以上就是如何使用Golang io实现流读写_结合Reader和Writer处理数据的详细内容,更多请关注php中文网其它相关文章!
每个人都需要一台速度更快、更稳定的 PC。随着时间的推移,垃圾文件、旧注册表数据和不必要的后台进程会占用资源并降低性能。幸运的是,许多工具可以让 Windows 保持平稳运行。
Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号