os.readfile和os.writefile适合小文件读写,自动管理文件句柄,但需注意权限、路径、编码等细节;大文件应使用bufio.scanner或io.copy流式处理;ioutil已弃用于go 1.16+。

用 os.ReadFile 和 os.WriteFile 快速读写小文件
90% 的日常场景——比如读配置、存日志片段、处理 JSON 配置文件——直接用这两个函数最省事,不用手动开闭文件句柄。
它们底层自动调用 os.Open 和 os.Create,读完/写完立刻 Close,避免忘记关文件导致的资源泄漏。
-
os.ReadFile返回[]byte,不是字符串;如果文件是 UTF-8 文本,需要显式转:string(data) -
os.WriteFile第三个参数是perm(权限),Windows 上基本无效,但 Linux/macOS 下写入新文件时必须设对,比如0644;设成0会导致文件不可读 - 文件大于几 MB 就别硬扛了——
ReadFile会一次性把全部内容加载进内存,OOM 风险明显
data, err := os.ReadFile("config.json")
if err != nil {
log.Fatal(err)
}
cfg := string(data) // 注意:这里只是转字符串,不校验编码
大文件或流式处理必须用 bufio.Scanner 或 io.Copy
想逐行读日志、边读边过滤、或者复制 GB 级视频片段?os.ReadFile 直接卡死。这时候得靠流式接口。
bufio.Scanner 默认单行上限 64KB,超长行会报 scanner.ErrTooLong;io.Copy 则适合整块搬运,比如从网络响应体写到本地文件。
- 用
scanner.Split(bufio.ScanLines)可以改成分割逻辑,但别自己写正则分割——性能差且容易出错 -
io.Copy内部用 32KB 缓冲区,足够通用;如需自定义缓冲大小,得套一层io.CopyBuffer - 别在循环里反复调用
os.Open+os.WriteFile处理多行——每轮都开闭文件,I/O 开销爆炸
f, _ := os.Open("access.log")
scanner := bufio.NewScanner(f)
for scanner.Scan() {
line := scanner.Text() // 注意:Text() 是拷贝,Bytes() 是切片引用
if strings.Contains(line, "ERROR") {
fmt.Println(line)
}
}
ioutil 已弃用,别再用 ioutil.ReadFile
Go 1.16 起,ioutil 包整体被移到 os 下,所有函数都迁走了。还在用 ioutil.ReadFile 的代码,升级后会编译失败。
不是“还能跑就不管”,而是模块依赖和静态分析工具(比如 golint、staticcheck)会直接标红警告,CI 流水线可能因此中断。
- 替换很简单:把
ioutil.ReadFile改成os.ReadFile,其他参数完全一致 - 如果项目还支持 Go
-
ioutil.TempDir也进了os,别漏掉
权限、路径、编码这些细节不处理,运行时才暴露
Go 不做运行前校验:路径不存在不报错(WriteFile 会尝试创建目录)、权限不够要等真正 Write 才 panic、UTF-8 解码错误更是沉默吞掉——全靠你手动检查 err。
尤其注意 os.WriteFile 对父目录无创建能力,"data/logs/app.log" 中 data/logs 不存在就会失败,得提前 os.MkdirAll。
- 路径拼接别用
+,用filepath.Join("data", "logs", "app.log"),否则 Windows/Linux 斜杠不一致 - 中文路径在 Windows 上一般没问题,但某些容器环境(如旧版 Docker Desktop)可能因挂载方式导致
open xxx: no such file - 读取非 UTF-8 文件(比如 GBK 日志)时,
string(data)不会报错,但显示乱码——得用golang.org/x/text/encoding显式解码
golang免费学习笔记(深入):立即使用
在学习笔记中,你将探索golang的核心概念和高级技巧!











