小文件读写应使用os.readfile和os.writefile,适用于配置文件、json/yaml解析、临时token等单次操作;大文件或需流式处理时必须用os.open+bufio.scanner或io.copy;ioutil在go 1.16+已彻底弃用。

小文件直接用 os.ReadFile 和 os.WriteFile;大文件或需控制流程时,必须走 os.Open + io.Copy 或 bufio.Scanner —— 别再碰 ioutil,Go 1.16+ 已彻底移除。
什么时候该用 os.ReadFile 而不是手动 os.Open/os.Close
90% 的配置读取、单次 JSON/YAML 解析、临时 token 写入、小日志快照等场景,os.ReadFile 就够了。它自动完成打开 → 读取 → 关闭,不漏关句柄,也不用写 defer。
- 错误必须检查:返回
"no such file or directory"或"permission denied"时不处理,后续操作大概率 panic -
os.ReadFile返回[]byte,要转字符串得显式写string(data),它不校验 UTF-8 - 写入权限参数(如
0644)只在 Linux/macOS 创建新文件时生效,Windows 忽略;设成0会导致文件不可读 - 它总是覆盖写,要追加?换
os.OpenFile+os.O_APPEND
为什么几十 MB 就不能用 os.ReadFile
它把整个文件一次性加载进内存,没流控、无缓冲区调节能力。几十 MB 就可能触发 runtime: out of memory,尤其在低配容器或嵌入式环境里更敏感。
- 日志分析、GB 级备份、边读边解密、实时过滤等场景,必须流式处理
-
bufio.Scanner默认单行上限 64KB,超长行会报scanner.ErrTooLong;可调但别乱改分割逻辑 -
io.Copy内部用 32KB 缓冲区,适合整块搬运(比如复制视频、保存 HTTP 响应体),不用手写循环 - 忘记
defer f.Close()是高频事故,Linux 下默认最多 1024 个打开文件,跑久直接卡死在too many open files
os.OpenFile 的 flag 组合决定实际行为
os.OpenFile 是底层统一入口,os.Create、os.Open 都是它的封装。真正控制“能不能写”“找不到是否创建”“是否清空”“是否追加”的,就是 flag 参数。
- 只读:
os.O_RDONLY - 读写 + 创建(不存在时):
os.O_RDWR | os.O_CREATE - 追加写(常用日志):
os.O_WRONLY | os.O_APPEND | os.O_CREATE - 覆盖写(清空后重写):
os.O_WRONLY | os.O_CREATE | os.O_TRUNC - 权限位(如
0644)仅在创建新文件时起作用,已存在文件的权限不会被修改
最常被忽略的是:os.OpenFile 第二个参数决定“能否写”,第三个参数只影响“新建时的权限”。很多人传了 0644 却发现文件不可写,其实是 flag 没设对 os.O_WRONLY 或 os.O_RDWR。
golang免费学习笔记(深入):立即使用
在学习笔记中,你将探索golang的核心概念和高级技巧!











