在golang中重命名之前关闭文件

时间:2016-03-06 12:44:36

标签: go deferred

当我使用golang进行一些文件操作时,我首先打开一个文件并将close()添加到defer列表中,然后我尝试重命名该文件。如果我手动关闭文件,延迟将再次关闭它。如果我等待延迟关闭它,重命名将导致错误,因为它没有关闭。代码如下

func main() {

    pfile1, _ := os.Open("myfile.log")
    defer pfile1.Close() //It will be closed again.
    ...
    ...
    pfile1.Close() //I have to close it before rename it.
    os.Rename("myfile.log", "myfile1.log")
}

我发现了一些丑陋的解决方案,比如创建另一个分隔打开文件的功能,下面有更好的解决方案吗?

func main() {

    var pfile1 *os.File
    ugly_solution(pfile1)

    os.Rename("myfile.log", "myfile1.log")
}

func ugly_solution(file *os.File) {
    file, _ = os.Open("myfile.log")
defer file.Close()
}

3 个答案:

答案 0 :(得分:1)

关于您的代码,有一些我不清楚的事情。

首先,为什么在重命名之前打开文件? os.Rename函数不需要这样做。该函数采用两个表示旧文件名和新文件名的字符串,不需要传递文件指针。

func main() {
    ...
    ...
    os.Rename("myfile.log", "myfile1.log")
}

假设您需要更改文件内容(根据ugly_solution方法似乎不是这种情况)并且您必须打开文件,那么为什么要推迟file.Close() ?如果您需要在同一方法中的某处显式调用该方法,则不必推迟该方法。简单地称之为。

func main() {
    pfile1, _ := os.Open("myfile.log")
    ...
    ...
    pfile1.Close()
    os.Rename("myfile.log", "myfile1.log")
}

答案 1 :(得分:1)

您可以将文件关闭并重命名为延迟:

func main() { 
    pfile1, _ := os.Open("myfile.log")
    defer func(){
        pfile1.Close()
        os.Rename("myfile.log", "myfile1.log")   
    }() 
    ...
    ...
}

答案 2 :(得分:0)

在您的样本中遇到的情况

也许您想遵循这种情况:

  • 轻松创建可识别的临时文件。
  • 写数据。
  • 关闭文件。
  • 如果成功重命名文件。

在这种情况下,您想遵循基础文件的OS系统操作,可能只是想不推迟IO.file上的关闭,因为您想获取关闭函数本身返回的错误。

此外,在这种情况下,您可能也想操作file.sync()。

请参见https://www.joeshaw.org/dont-defer-close-on-writable-files/