最常用且安全的文件拷贝方式是组合os.Open、os.Create和io.Copy;需用os.MkdirAll确保目标目录存在;io.Copy仅复制内容,保留元信息需额外调用os.Chmod和os.Chtimes;大文件场景推荐io.CopyBuffer控制缓冲区大小。

用 io.Copy 配合 os.Open 和 os.Create 是最常用且安全的做法
Go 标准库没有直接的 CopyFile 函数,但组合 os.Open、os.Create 和 io.Copy 就能可靠完成拷贝。它自动处理缓冲、流式读写和错误传播,比手动 Read/Write 更简洁、更健壮。
常见错误是忽略目标目录是否存在:如果 os.Create 的路径含多级目录(如 "out/a/b/c.txt"),会因父目录不存在而报 "no such file or directory"。必须提前用 os.MkdirAll 创建路径。
示例关键步骤:
- 用
os.Open(src)打开源文件(只读) - 用
os.MkdirAll(filepath.Dir(dst), 0755)确保目标目录存在 - 用
os.Create(dst)创建目标文件(会截断已有内容) - 调用
io.Copy(dstFile, srcFile)完成拷贝 - 按顺序关闭两个文件(注意错误检查)
需要保留文件元信息?得手动复制 Mode 和 ModTime
io.Copy 只复制内容,不保留权限、修改时间等元数据。若需完整克隆(比如备份场景),必须额外调用 os.Chmod 和 os.Chtimes。
立即学习“go语言免费学习笔记(深入)”;
注意两点:
-
os.Stat返回的os.FileInfo中Mode()包含权限位,但创建文件时os.Create固定用0666,所以必须后续Chmod -
ModTime()是time.Time类型,可直接传给os.Chtimes;但目标文件需已存在(即Create后再调用) - Windows 下
Chtimes对AccessTime支持有限,通常只设ModTime即可
大文件或高并发拷贝时,io.CopyBuffer 能显式控制内存占用
默认 io.Copy 使用 32KB 缓冲区,在拷贝 GB 级文件或大量小文件时,可能因频繁系统调用或 GC 压力影响性能。此时换成 io.CopyBuffer 并传入自定义切片,能更精准控制缓冲大小。
例如:
buf := make([]byte, 1<<20) // 1MB buffer _, err := io.CopyBuffer(dstFile, srcFile, buf)
但要注意:
- 缓冲区过大(如 >10MB)可能挤占其他 goroutine 内存
- 过小(如
- 缓冲区应复用(如从
sync.Pool获取),避免高频分配
第三方库 fsutil.CopyFile 适合快速集成但依赖引入
如果项目已用 golang.org/x/tools 或能接受新依赖,golang.org/x/tools/fs/internal/fsutil.CopyFile 提供了带元数据复制、符号链接处理、原子写入(先写临时文件再 rename)的封装。
但它不是标准库,且 fsutil 属于内部包(路径含 internal),官方不保证兼容性。生产环境建议仅在明确需要原子性或跨平台符号链接支持时选用,并锁定 commit hash。
容易被忽略的是:原子写入虽防中断损坏,但 rename 在不同文件系统间(如 src 在 ext4、dst 在 NFS)可能失败,此时仍要 fallback 到普通拷贝。










