os.ReadFile和os.WriteFile适用于小文件读写,但大文件需用os.Open+bufio.Scanner流式处理;注意路径、权限、perm参数及Scanner缓冲区设置。

Go 语言读写文件没有“默认最简方案”,直接用 os.ReadFile 和 os.WriteFile 就够大多数场景,但它们会把整个文件加载进内存——大文件或流式处理时必须换方式。
用 os.ReadFile 和 os.WriteFile 快速读写小文本/配置文件
这两个函数是 Go 1.16+ 内置的便捷封装,底层调用 os.Open + io.ReadAll(读)或 os.Create + io.Copy(写),省去手动关闭文件的步骤。
常见错误现象:open /tmp/config.json: no such file or directory —— 路径不存在且父目录未创建;permission denied —— 写入路径无写权限(尤其在 Linux/macOS 的非用户目录下)。
使用场景:读取 JSON/YAML 配置、写入日志快照、生成临时 token 文件等单次小数据操作。
实操建议:
- 读取前不用检查文件是否存在,
os.ReadFile返回error时直接判断errors.Is(err, os.ErrNotExist) - 写入时第三个参数是
perm(如0644),别传0777—— 这不会让所有用户都能执行,反而可能触发安全策略拦截 - 如果要追加内容,不能用
os.WriteFile(它总是覆盖),得换os.OpenFile+file.Write
用 bufio.Scanner 逐行读大文本,避免 OOM
当文件超过几十 MB,或你只关心某几行(比如解析日志中的 ERROR 行),os.ReadFile 会把全部内容塞进内存,容易触发 runtime: out of memory。
正确做法是流式读取:os.Open 打开后传给 bufio.NewScanner,再用 Scan() 循环获取每行。
注意点:
-
Scanner默认单行上限是 64KB,超长行会报scanner: token too long—— 用scanner.Buffer(make([]byte, 4096), 1 手动扩容 - 扫描完必须检查
scanner.Err(),否则 IO 错误(如磁盘突然拔出)会被静默忽略 - 不要在循环里用
scanner.Text()结果做长期引用——下一次Scan()会复用底层 buffer,旧值被覆盖
用 os.OpenFile 精确控制读写模式和权限
os.OpenFile 是底层统一入口,os.ReadFile、os.WriteFile、os.Create 全是它的封装。需要以下情况时必须用它:
- 以
O_APPEND模式追加日志(os.WriteFile不支持) - 同时读写一个文件(如编辑器保存时先读原内容再改写)
- 指定
syscall.O_SYNC强制落盘(关键数据防断电丢写) - 在 Windows 上打开带
:$DATA的 NTFS 流文件(极少见但存在)
参数差异重点:
- flag 参数组合要小心:
os.O_RDWR | os.O_CREATE可以,但os.O_RDONLY | os.O_CREATE会 panic —— 只读模式无法创建 - perm 参数仅在
O_CREATE生效,且仅影响新建文件;已存在文件的权限不变 - Linux 下若用
O_TRUNC清空文件再写,要注意其他进程是否正mmap该文件——截断后 mmap 区域行为未定义
读写二进制文件别用 string() 强转 []byte
很多新手把 os.ReadFile 返回的 []byte 直接转成 string 再传给 strings.Split 或正则,这在处理图片、PDF、ZIP 时会导致乱码甚至 panic(非法 UTF-8)。
真正该做的:
- 读二进制就保持
[]byte类型,用bytes.Contains、bytes.Index等函数处理 - 写二进制时确保源数据是
[]byte,别从string转——string在 Go 中是只读 UTF-8 序列,不是字节容器 - 如果必须解析二进制协议(如 ELF、PNG header),用
binary.Read+struct{}+binary.LittleEndian,别手撕字节位移
最容易被忽略的是:Windows 上用 \r\n 换行的文本文件,在 Linux 用 bufio.Scanner 读时自动处理了,但你自己用 bytes.Split(buf, []byte("\n")) 就会漏掉 \r —— 这类细节不跑真实环境根本发现不了。
golang免费学习笔记(深入):立即使用
在学习笔记中,你将探索golang的核心概念和高级技巧!











