os.Create会清空已有内容是因为它默认使用O_CREATE|O_TRUNC|O_WRONLY模式,O_TRUNC导致文件被截断为0字节;避免覆盖应使用O_EXCL,追加写入需用O_APPEND。
os.Create 会清空已有内容?os.Create 的行为是「打开或新建」,但关键点在于它总是以 O_CREATE | O_TRUNC | O_WRONLY 模式调用底层系统调用。这意味着:如果文件已存在,O_TRUNC 会直接截断为 0 字节——不是报错,也不是追加,而是静默清空。
os.OpenFile(path, os.O_CREATE|os.O_WRONLY|os.O_EXCL, 0644),O_EXCL 在文件存在时返回 *os.PathError
os.OpenFile(path, os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0644)
file.Close(),否则内容可能未刷盘(尤其在短生命周期程序中)file, err := os.Create("data.txt")
if err != nil {
log.Fatal(err)
}
defer file.Close()
file.WriteString("hello\n") // 不会自动换行,需手动加 \n
os.Remove 的真实行为os.Remove 只能删除空目录;对非空目录会返回 invalid argument(Windows)或 directory not empty(Unix)。它也不会递归删除子项,这点和 shell 的 rm -r 完全不同。
os.Remove("file.txt")
os.RemoveAll("dir/") —— 注意末尾斜杠不影响行为,但路径必须存在os.Remove 和 os.RemoveAll 都只删链接,不碰目标err != nil,务必检查err := os.Remove("old.log")
if err != nil {
if os.IsNotExist(err) {
fmt.Println("文件不存在,无需删除")
} else {
log.Printf("删除失败: %v", err)
}
}
"dir/filename"?Go 的 os 包内部使用操作系统原生路径分隔符,但硬写 / 或 \ 会导致 Windows 下打开失败(例如 "C:\temp\file.txt" 中的 \t 被解释为制表符)。
path/filepath.Join("dir", "subdir", "file.txt") 拼接路径filepath.Clean() 规范化,它会处理 ../、重复分隔符、结尾斜杠等filepath.IsAbs(path),不要用字符串前缀判断(C: 在 Windows 是绝对路径,/ 在 Unix 是)ioutil.TempDir 还是 os.MkdirTemp?ioutil.TempDir 已在 Go 1.16+ 被标记为 deprecated,所有新代码必须用 os.MkdirTemp。两者都生成唯一路径,但后者更安全:
os.MkdirTemp("", "prefix-"):第一个参数为 "" 表示使用默认临时目录(os.TempDir()),无需手动指定 /tmp 或 C:\Temp
os.MkdirAll
os.CreateTemp("", "prefix-*.txt"),同样支持通配符 * 占位随机字符串dir, err := os.MkdirTemp("", "test-*.d")
if err != nil {
log.Fatal(err)
}
defer os.RemoveAll(dir) // 清理务必放 defer,且放在创建之后

实际项目里最常被忽略的是错误检查粒度——比如用 os.Remove 删除一个预期一定存在的配置文件,却没区分「不存在」和「权限拒绝」,导致故障时难以定位是部署问题还是代码逻辑问题。