Go不支持批量写入多个文件,必须显式控制每个文件的打开、写入、关闭;os.WriteFile仅适用于单文件覆盖写,无并发能力,高频小数据写入需用bufio.Writer优化性能。

不能直接“批量写入多个文件”——Go 没有内置的 multi-file write 接口,必须显式控制每个文件的打开、写入、关闭,否则会出错或丢数据。
os.WriteFile 适合单文件覆盖写,不适用于多文件批量写入
很多人误以为 os.WriteFile 能“一次写多个”,但它只接受一个 filename 参数。传入切片或循环调用它,本质仍是串行操作,且每次都会重新打开/关闭文件,无并发优势。
- 它内部等价于
os.OpenFile(..., os.O_CREATE|os.O_TRUNC|os.O_WRONLY, ...),强制截断,不适合追加场景 - 频繁调用
os.WriteFile写小数据(如每条日志一行)性能差:无缓冲、无句柄复用、无错误隔离 - 若某次写入失败(磁盘满、权限不足),你只能靠外层
for循环捕获,无法统一控制重试或跳过
并发写多个文件必须用 goroutine + sync.WaitGroup
真正高效的多文件写入,是让每个文件由独立 goroutine 处理,避免阻塞。但必须用 sync.WaitGroup 等待全部完成,否则主函数可能提前退出,导致文件没写完就关闭进程。
- 闭包中传递文件名时,必须把
filename作为参数传入 goroutine,否则所有 goroutine 共享同一个变量,最终全写到最后一个文件 - 每个 goroutine 应独立打开、写入、关闭自己的文件;不要共享
*os.File句柄,否则 Windows 下易报invalid argument - 建议限制并发数,比如用带缓冲 channel 控制最大 10 个 goroutine 同时写,防止打开太多文件句柄(Linux 默认 ulimit -n 通常为 1024)
追加写多个文件时,os.O_APPEND 不等于线程安全
即使对每个文件都用了 os.O_APPEND | os.O_WRONLY | os.O_CREATE,也不能在多个 goroutine 中直接并发调用 f.WriteString —— 因为 Go 的 WriteString 不是原子操作,底层先拷贝进 buffer 再 syscall,多个 goroutine 的 buffer 写入会交错。
立即学习“go语言免费学习笔记(深入)”;
- 现象:两行日志粘连(
"logA\nlogB\n"变成"logAlogB\n\n"),或某次写入被截断 - 正确做法:要么每个文件配一个 mutex(
map[string]*sync.Mutex),要么把写请求发给一个专用 writer goroutine(channel 聚合) - Windows 下还要注意换行符:用
"\r\n",别依赖\n自动转换
大文件或高频写入务必用 bufio.Writer
直接对 *os.File 频繁 Write 或 WriteString,每次都是系统调用,开销极大。尤其写日志类多小文件时,性能差距可达 5–10 倍。
- 为每个文件创建独立的
bufio.NewWriter,缓冲区大小建议设为 64KB:bufio.NewWriterSize(f, 64*1024) -
defer wr.Flush()不可靠:panic 时 flush 可能不执行;关键逻辑应wr.Flush(); f.Close()显式调用 - 如果某次写入失败(
wr.Write返回 error),要立即break并关闭该文件,避免后续写入继续失败却无感知
最常被忽略的是:写入后没检查 Close() 的返回值。它可能因缓冲未刷盘而失败,尤其 NFS 或 USB 设备上——Close() 报错 ≠ Write() 报错,两者必须分开判断。


















