os.Open
opens a file in read-only mode. You should use os.OpenFile
instead:
os.OpenFile("file.csv", os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0644)
FYI, note that os.Create
also works but it will truncate the file if it already exists, as you mention. This may or may not be what you want.
As of why you see no error, it's because writes are buffered and the content isn't actually written until you call w.Flush
. This is mentioned in w.Write
documentation:
Writes are buffered, so Flush must eventually be called to ensure that the record is written to the underlying io.Writer.
Though w.Flush
itself is deferred in your code, and doesn't return an error anyway. You can check for errors with w.Error()
.
If you place the two calls at the end of your function, as follows, you will eventually see the 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
And as a matter of fact the error means that you opened the file with the wrong mode flags. More details in: Golang bad file descriptor
If you want to keep deferring w.Flush()
, place it together with w.Error()
in a function literal, which if used in combination with named return params, allows you to propagate the error, if any.
For example:
func writeToCsv() (err error) {
// ...open file
w := csv.NewWriter(file)
defer func() {
w.Flush()
err = w.Error()
}()
// ...rest of the function
}