Go 文件与 IO 学习笔记:从文件读写理解 Go 的 IO 设计
2026/8/2 11:35:35 网站建设 项目流程

刚开始学习 Go 的文件操作时,最容易产生一个疑问:

为什么 Go 里面读取文件要用os,又出现了io,还有bufio

刚开始看这些包的时候,会感觉它们功能很重复。

比如读取文件:

file.Read()

也可以:

io.ReadAll(file)

还可以:

bufio.NewReader(file)

到底应该用哪个?

其实它们负责的事情完全不同。


一、先理解 IO 是什么

IO 的全称是:

Input / Output

也就是:

输入和输出。

简单理解:

程序需要和外部交换数据。

例如:

读取文件:

硬盘 | | 数据 ↓ Go程序

写入文件:

Go程序 | | 数据 ↓ 硬盘

这就是 IO。


二、Go 为什么设计 Reader 和 Writer?

假设没有接口。

读取文件:

file.Read()

读取网络:

conn.Receive()

读取字符串:

string.Get()

每一种数据来源都有自己的方法。

那么代码会非常混乱。

Go 的设计:

不关心数据来自哪里。

只要求:

你能不能读取?

如果能:

实现:

io.Reader

你能不能写入?

实现:

io.Writer

于是:

文件:

os.File

可以读。

字符串:

strings.Reader

也可以读。

网络:

net.Conn

也可以读。

它们虽然来源不同,但是使用方式一样:

Read()

三、第一次读取文件

最简单:

package main import ( "fmt" "os" ) func main(){ file,err:=os.Open("hello.txt") if err!=nil{ return } defer file.Close() buf:=make([]byte,10) n,err:=file.Read(buf) fmt.Println(string(buf[:n])) }

这个过程:

打开文件 ↓ 创建存储空间 ↓ Read读取 ↓ 打印数据

但是这里有一个问题:

如果文件:

10GB

怎么办?

你不能:

make([]byte,10GB)

全部放内存。

所以出现:


四、流式读取

Go 不喜欢:

“一次性拿完”。

更推荐:

“一点一点处理”。

例如:

for{ n,err:=file.Read(buf) if n>0{ 处理数据 } if err==io.EOF{ break } }

这就是流式 IO。

类似:

喝水。

不是一次喝完一桶。

而是一口一口喝。


五、bufio 为什么出现?

如果每次:

Read()

都会访问磁盘。

比如:

读取一万个字符。

可能:

读取1个字符 访问磁盘 读取1个字符 访问磁盘 ...

效率很低。

所以:

bufio 增加缓存。

变成:

文件 ↓ bufio缓存 ↓ 程序

一次读取一批数据。


六、文件复制为什么用 io.Copy?

以前:

我们可能这样:

for{ 读取 写入 读取 写入 }

但是 Go 已经帮我们封装:

io.Copy(dst,src)

它内部:

Reader ↓ 缓冲 ↓ Writer

自动完成。

所以:

文件复制:

io.Copy(target,source)

就是最标准写法。


七、filepath 解决什么问题?

很多初学者会这样:

path := "data/"+name

Linux 可以。

Windows:

可能出现问题。

所以:

filepath.Join()

帮你处理不同系统路径。


总结

学习 Go IO 最重要的不是记:

os.OpenFile bufio.Scanner filepath.Ext

而是理解:

数据从哪里来? ↓ Reader ↓ 程序处理 ↓ Writer ↓ 数据到哪里去?

文件:

os.File

网络:

net.Conn

内存:

bytes.Buffer

最后都会统一成:

io.Reader io.Writer

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询