如何打印目录中文件的内容,但忽略以写模式打开的文件?

时间:2018-12-11 16:58:55

标签: go

我有一个goroutine,它定期检查目录中的新文件,然后打印文件的内容。但是,还有另一个goroutine可以创建一个文件,然后将内容写入其中,然后保存该文件。

如何忽略目录中以WRITE模式打开的文件?

示例代码:

for {
 fileList, err := ioutil.ReadDir("/uploadFiles")
  if err != nil {
     log.Fatal(err)
     continue
  }

 for _, f := range fileList {
      log.Println("File : ", f.Name())
      go printContents(f.Name())
 }

 time.Sleep(time.Second * 5)
}

在printContents goroutine中,我想忽略以WRITE模式打开的文件。

1 个答案:

答案 0 :(得分:0)

这不是怎么做。

我可以想到以下这些选择:

  • 如果两个goroutine都在同一程序中运行, 几乎没有问题:使“生产者” goroutine寄存器 已完成修改为某些文件的文件名 注册表,并读取(删除)“消费者” goroutine 从该注册表中。

    在最简单的情况下,它可能是缓冲的通道。

    如果生产者的工作速度比消费者快得多, 而且您由于某种原因不想阻止前者 那么由互斥锁保护的切片就可以满足要求。

  • 如果goroutine在相同的不同进程中工作 机器,但您控制两个程序,使生产者 流程将相同的数据传达给使用者流程 通过任何合适的IPC。

    哪种方法做IPC更好,取决于如何 进程启动,交互等。

    有多种选择。

  • 如果您同时控制两个进程,但又不想弄乱 它们之间的IPC(也有原因),然后使生产者 遵循有关如何写入文件的最佳做法 (稍后会详细介绍),并让消费者使用任何 文件系统监视工具,用于报告生产者生产后创建(“显示”)哪些文件。 您可以从github.com/fsnotify/fsnotify开始。

    要正确写入文件,生产者必须写入文件 数据到一个临时文件,即位于同一文件中的一个文件 目录,但文件名易于理解 表示文件尚未完成,例如, “ .foobar.data.part”或“ foobar.data.276gd14054.tmp”可以写入“ foobar.data”。 (存在其他方法,但是这种方法足以 开始。)

    文件准备好后,生产者必须重命名 文件从其临时名称到其“适当”的最终名称。 此操作在所有明智的OS /文件系统上都是原子的, 并从PoV原子地使文件“跳入existense” 的消费者。例如inotify on Linux generates an event of type "moved to" for such an appearance

    如果您不想自己做正确的事情,那么github.com/dchest/safefile是跨平台的好起点。

    如您所见,通过这种方法,您知道 该文件仅根据报告的事实完成 出现了。

  • 如果您不控制生产者,则可能需要诉诸 猜。

    最简单的方法是再次监视文件系统 事件-但这一次是“文件更新”事件,而不是“文件已创建”事件 事件。对于每个报告为已更新的文件,您都必须记住 该事件的时间戳记,并且经过一定时间后,您可以声明该文件是由生产者完成的。

    IMO,这种方法是最糟糕的,但是如果您没有 更好的选择至少是一些东西。