Go文件写入中途崩溃时,需用.tmp临时文件+原子重命名、.meta记录偏移并fsync落盘、避免defer close,且os.OpenFile须用os.O_CREATE|os.O_RDWR配合Seek定位写入。

文件写入中途崩溃时如何保留已写内容
Go 本身不提供“原子性断点续传”原语,必须靠手动分阶段 + 状态标记实现。关键不是捕获 panic,而是预判哪些环节可能失败(磁盘满、权限丢失、网络挂起),并在每个临界点落盘临时状态。
典型做法是:先写入 .tmp 后缀临时文件,写完调用 os.Rename 原子替换目标文件;同时在同目录下维护一个 .meta 文件记录当前写入偏移量。这样即使进程被 kill,重启后也能读 .meta 并从断点继续。
-
os.Rename在同一文件系统内是原子的,跨分区会失败,需提前检查os.SameFile - 写
.meta必须在每次成功写入数据块后立即fsync,否则缓存未刷盘会导致元数据丢失 - 不要用
defer file.Close()包裹整个写入流程——panic 时 defer 可能来不及执行,应显式 close 并检查 err
读取大文件时 I/O 中断的重试与偏移恢复
使用 io.ReadAt 或 file.Seek + io.Read 组合时,若底层连接中断(如 NFS 挂载点失效),Read 会返回 io.ErrUnexpectedEOF 或具体 syscall 错误(如 syscall.ESTALE),而非阻塞等待。
此时不能直接重试整个读取,而应基于当前 file.Seek(0, io.SeekCurrent) 获取已读偏移,再从该位置继续。
立即学习“go语言免费学习笔记(深入)”;
Go 配置库,使用 spf13/viper — 分层优先级(flag > env >file > KV > default),提供 BindPFlag/BindPFlags、SetEnvPrefix + SetEnvKeyReplace 等功能。
- 每次
Read后立刻用file.Seek(0, io.SeekCurrent)记录位置,别依赖循环变量计数——实际读取字节数可能小于预期 - 对网络文件系统,建议设置
syscall.SetDeadline防止无限 hang,但注意 Go 标准库os.File不支持 deadline,需用net.Conn封装或改用os.OpenFile配合自定义 reader - 遇到
syscall.EINTR可安全重试;遇到syscall.EBADF说明文件描述符已失效,必须重新os.Open
使用 sync.Mutex 保护断点状态时的死锁风险
多个 goroutine 并发写同一文件时,常误以为加个 sync.Mutex 就能解决竞争。但若在持有锁期间调用可能阻塞的 I/O(如 file.Write),且该 I/O 又因外部原因长期不返回,就会导致其他 goroutine 永久等待锁。
真正需要互斥的只是元数据更新(如更新 .meta 中的 offset 字段),I/O 本身可并行,只要保证写入顺序和 offset 计算正确。
- 把锁的作用域严格限制在读/写
.meta文件的几行代码内,绝不包裹file.Write - 用
atomic.StoreInt64替代 mutex 管理纯数值型偏移量,性能更好且无死锁可能 - 如果必须串行写入(如追加日志),优先考虑
bufio.Writer+ 定期Flush,减少系统调用次数,而非粗粒度锁
os.OpenFile 的 flag 组合影响断点行为
错误的 flag 会导致无法续传。例如用 os.O_TRUNC 打开已有文件,会清空内容;用 os.O_CREATE | os.O_WRONLY 而不加 os.O_APPEND,则每次写都从开头覆盖。
断点续传场景下,最常用的是 os.O_CREATE | os.O_RDWR,配合 file.Seek(offset, io.SeekStart) 定位,再写入新数据。
- 务必检查
os.OpenFile返回的*os.File是否为 nil,且 err == nil;某些文件系统在只读挂载下会静默忽略O_RDWR,返回可写句柄但实际写入失败 - Linux 下
os.O_SYNC会让每次Write都等待磁盘落盘,延迟高但断电不丢数据;os.O_DSYNC只保证数据落盘,不等元数据(如 mtime),适合平衡可靠性与性能 - Windows 上
os.O_APPEND和Seek冲突,调用Seek后再Write会覆盖而非追加,必须用SetEndOfFileWinAPI 或改用os.WriteFile
断点逻辑越靠近存储层(比如直接操作 offset 和 syscall),越容易受 OS 差异影响;封装成统一接口时,要专门测试 Windows、ext4、XFS、NFSv4 的行为一致性。

















