在Go中,是否有一种独立于os的方式来自动覆盖文件?

时间:2015-05-21 22:11:58

标签: file go atomic

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

我最初的想法是:

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

1 个答案:

答案 0 :(得分:4)

os.Rename调用syscall.Rename,对于Linux / UNIX,它使用重命名系统调用(原子*)。在Windows syscall.Rename调用MoveFileW,假设源和目标位于同一设备(可以安排),文件系统是NTFS(通常是这种情况)是原子*。

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

这在我的用例中适用于我:

  1. One Go进程获取更新并重命名文件以交换更新。
  2. 另一个Go流程正在使用fsnotify查看文件更新,并在文件更新时重新mmap
  3. 在上面的用例中,简单地使用os.Rename对我来说非常有效。

    进一步阅读:

    1. Is rename() atomic?“是的,没有。重命名()是原子的,假设操作系统没有崩溃......”
    2. Is an atomic file rename (with overwrite) possible on Windows?
    3. *注意:我想指出当人们谈论原子文件系统文件操作时,从应用程序的角度来看,它们通常意味着操作发生或不发生({{3}从用户的角度来看,可以提供帮助)。如果您在原子内存操作意义上使用原子,很少有文件系统操作(在直接I / O [journaling之外]一个块写入和禁用磁盘缓冲的读取)可以被认为是真正的原子。