golang csv.write 没有写入但没有错误

golang csv.write not writing but no errors

我正在尝试打开现有的 csv 文件并写入;但是,文件 returns 是空的。这是我的代码。

file, err := os.Open("file.csv")
    if err != nil {
        log.WithError(err)
    }

    defer file.Close()

    w := csv.NewWriter(file)
    defer w.Flush()

    var headers = []string{"h1", "h2", "h3", "h4"}
    writeHeadersErr := w.Write(headers)
    if writeHeadersErr != nil {
        log.WithError(writeHeadersErr)
        file.Close()
    }

不确定如何解决这个问题,因为我没有看到任何错误记录。

您需要检查来自 Flush()error:

w.Flush()

if err := w.Error(); err != nil {
    log.Fatal(err) // write file.csv: bad file descriptor
}

这将表明您打开的文件是为了阅读而不是写作。所以要修复:

//file, err := os.Open("file.csv") // read file
file, err := os.Create("file.csv") // create file
if err != nil {
    log.Fatal(err)
}

https://play.golang.org/p/QhpYnrc7cmR

os.Open opens a file in read-only mode. You should use os.OpenFile 改为:

os.OpenFile("file.csv", os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0644)

仅供参考,请注意 os.Create 也有效,但如您所述,如果文件已存在,它会截断该文件。这可能是也可能不是您想要的。

至于为什么你看不到错误,这是因为写入被缓冲并且内容在你调用 w.Flush 之前并没有真正写入。 w.Write 文档中提到了这一点:

Writes are buffered, so Flush must eventually be called to ensure that the record is written to the underlying io.Writer.

虽然 w.Flush 本身在您的代码中被延迟了,并且 return 也不是错误。您可以使用 w.Error().

检查错误

如果将这两个调用放在函数的末尾,如下所示,您最终会看到错误:

    file, err := os.Open("file.csv")
    if err != nil {
        log.WithError(err)
    }
    defer file.Close()

    w := csv.NewWriter(file)
    // ... write to the file
    w.Flush()
    err = w.Error() // write file.csv: bad file descriptor

事实上,错误意味着您打开文件时使用了错误的模式标志。更多详情见:

如果您想继续延迟 w.Flush(),请将其与 w.Error() 一起放在函数文字中,如果与命名的 return 参数结合使用,则可以传播错误,如果有的话。

例如:

func writeToCsv() (err error) {
    
    // ...open file
    w := csv.NewWriter(file)
    defer func() {
        w.Flush()
        err = w.Error()
    }()
    // ...rest of the function
}