【问题标题】:When I io.Copy a file, it doesn't block and trying to use it might fail until it finishes当我 io.Copy 一个文件时,它不会阻塞并且尝试使用它可能会失败,直到它完成
【发布时间】:2021-07-22 03:51:46
【问题描述】:

我有这个代码(或多或少):

resp, err := http.Get(url)
if err != nil {
    // handle error
}

if resp.StatusCode != http.StatusOK {
    // handle error
}

out, err := os.Create(filepath)
if err != nil {
    return err
}

// Write the body to file
_, err = io.Copy(out, resp.Body)
resp.Body.Close()
out.Close()

我的问题是,如果我立即尝试做某事(例如,获取此文件的哈希),那么我会看到它仍在复制一段时间。

起初我推迟了 out.Close(),但我认为我需要在 io.Copy 之后进行 out.Close,这将阻塞直到它完成。或者我是这么想的。 这没有用,我仍然有同样的问题。

如何阻止或等待 io.Copy 操作完成?

谢谢!

【问题讨论】:

  • @JimB 所说的 +1。如果这不能解决您的问题,也许您可​​以尝试在out 上调用Sync 来强制执行fsync 系统调用。
  • How do I block or wait for the io.Copy operation to finish? 您编写指令来同步访问。或者以某种方式调用该函数将阻塞,直到它的工作完成,然后再继续执行另一个函数。我觉得你没有讲完整个故事。
  • 有时我们不需要同步,我们可以一次完成所有的事情。 stackoverflow.com/questions/62319053/…
  • 问题是,如果我等待它会起作用。如果我在循环中对文件进行采样,我会看到它会发生变化,直到它稳定(完成) - 例如在循环中获取哈希。它仍然失败,我添加了同步,它似乎工作(很难确定,这不是 100% 可重现的)。有什么理由应该调用同步吗?为什么我需要强迫它,似乎它无论如何都会发生。 @EmilePels - 你可以把它写成答案,我会接受它
  • @RoyCa 很高兴它有帮助。我已经提交了一个带有更详细解释的答案,并且我还在那里引用了一些文档。

标签: go


【解决方案1】:

您可能正在访问一些磁盘缓冲区/缓存,您的操作系统或磁盘设备在实际将写入持久化到磁盘之前将一些数据保存在内存中。

打电话

out.Sync()

强制执行fsync 系统调用,这将指示操作系统强制刷新缓冲区并将数据写入磁盘。我建议在io.Copy 调用返回之后调用out.Flush()

您可能会感兴趣的相关文档:

【讨论】:

  • 真的很惊讶out.Close() 不会在有未写入的缓冲数据时隐式进行同步。这似乎暴露了io.Copy 等用户不必担心的内部问题。
  • @colm.anseo:这些年来我忘记了自己,stackoverflow.com/questions/705454/…
猜你喜欢
  • 1970-01-01
  • 2015-07-12
  • 2012-12-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-04-21
  • 2020-01-23
相关资源
最近更新 更多