是否有一种 os 独立的方式来自动覆盖文件?

Is there an os-independent way to atomically overwrite a file?

如果文件已经存在,我想覆盖它。如果它不存在,我想创建它并写入它。我宁愿不必使用像 lockfile 这样的第三方库(它似乎可以处理所有类型的锁定。)

我最初的想法是:

  1. 使用随机生成的大 ID 写入临时文件以避免冲突。
  2. Rename 临时文件名 -> 新路径名。

os.Rename calls syscall.Rename which for Linux/UNIXs uses the rename syscall (which is atomic*). On Windows syscall.Rename calls MoveFileW which assuming the source and destination are on the same device (which can be arranged) and the filesystem is NTFS(通常是这种情况)是原子*。

我会注意确保源和目标位于同一设备上,这样 Linux 重命名不会失败,并且 Windows 重命名实际上是原子的。正如 Dave C 在上面提到的那样,在与现有文件相同的目录中创建临时文件(通常使用 ioutil.TempFile)是可行的方法;这就是我进行原子重命名的方式。

这适用于我的用例:

  1. 一个 Go 进程获取更新并重命名文件以交换更新。
  2. 另一个 Go 进程正在监视文件更新 fsnotify and re-mmaps 更新文件。

在上面的用例中,简单地使用 os.Rename 对我来说效果很好。

进一步阅读:

  1. Is rename() atomic? "Yes and no. rename() is atomic assuming the OS does not crash...."
  2. Is an atomic file rename (with overwrite) possible on Windows?

*注意:我确实想指出,当人们谈论原子文件系统 file 操作时,从应用程序的角度来看,他们通常意味着操作发生或不发生( journaling can help with) from the users perspective. If you are using atomic in the sense of an atomic memory operation, very few filesystem operations (outside of direct I/O [O_DIRECT]一个块在禁用磁盘缓冲的情况下写入和读取)可以被认为是真正的原子。