Golang中如何同时创建并写入两个CSV文件?
解决多CSV文件同时写入的问题
嘿,我明白你的需求啦——要同时往两个CSV文件里分别写入成功和错误记录,你的代码思路其实是对的,只是在初始化Writer的时候犯了一个关键的小错误,导致两个Writer都指向了同一个文件。咱们来一步步修正并优化它:
首先指出代码里的核心问题
在init函数里,你把csvWriterError错误地关联到了csvSuccess文件:
csvWriterError = csv.NewWriter(csvSuccess) // 这里写错了!
这就导致不管调用WriteRecordSuccess还是WriteRecordError,数据都会写到同一个文件里,自然达不到区分写入的效果。
修正后的完整实现
下面是修正并优化后的代码,我还完善了错误处理和资源管理的细节:
package test import ( "encoding/csv" "os" "sync" ) var ( csvSuccess *os.File csvError *os.File csvWriterSuccess *csv.Writer csvWriterError *csv.Writer mutex *sync.Mutex ) func init() { var err error // 分别创建两个文件,每个操作都单独检查错误 csvSuccess, err = os.Create("success-result.csv") if err != nil { panic("Failed to create success result file: " + err.Error()) } csvError, err = os.Create("error-result.csv") if err != nil { // 如果创建错误文件失败,要先关闭已经打开的成功文件,避免资源泄漏 _ = csvSuccess.Close() panic("Failed to create error result file: " + err.Error()) } // 分别为两个文件初始化独立的Writer csvWriterSuccess = csv.NewWriter(csvSuccess) csvWriterError = csv.NewWriter(csvError) // 这里修正为csvError mutex = &sync.Mutex{} } func WriteRecordSuccess(record []string) { mutex.Lock() defer mutex.Unlock() // 使用defer确保锁一定会释放 if err := csvWriterSuccess.Write(record); err != nil { panic("Error writing success record: " + err.Error()) } csvWriterSuccess.Flush() // 写入后立即刷新缓冲区到文件 // 检查Flush是否有错误 if err := csvWriterSuccess.Error(); err != nil { panic("Error flushing success writer: " + err.Error()) } } func WriteRecordError(record []string) { mutex.Lock() defer mutex.Unlock() if err := csvWriterError.Write(record); err != nil { panic("Error writing error record: " + err.Error()) } csvWriterError.Flush() if err := csvWriterError.Error(); err != nil { panic("Error flushing error writer: " + err.Error()) } } func CloseCSVFiles() { // 先刷新所有缓冲区 csvWriterSuccess.Flush() csvWriterError.Flush() // 检查Flush错误 if err := csvWriterSuccess.Error(); err != nil { panic("Error flushing success writer on close: " + err.Error()) } if err := csvWriterError.Error(); err != nil { panic("Error flushing error writer on close: " + err.Error()) } // 同步文件到磁盘,确保数据写入 if err := csvSuccess.Sync(); err != nil { panic("Failed to sync success file: " + err.Error()) } if err := csvError.Sync(); err != nil { panic("Failed to sync error file: " + err.Error()) } // 关闭文件,检查关闭错误 if err := csvSuccess.Close(); err != nil { panic("Failed to close success file: " + err.Error()) } if err := csvError.Close(); err != nil { panic("Failed to close error file: " + err.Error()) } }
关键说明
- 区分不同的Writer:每个
*csv.Writer都是独立的指针实例,只要你在初始化时分别传入不同的*os.File对象,它们就会对应各自的文件,操作不同的Writer自然会写入到对应的文件中。 - 锁的使用:我用
defer mutex.Unlock()替代了手动在末尾解锁,这样即使函数中途panic,锁也能正常释放,避免死锁。 - 完善错误处理:每个文件操作(创建、Flush、Sync、Close)都添加了错误检查,还在创建第二个文件失败时关闭已打开的第一个文件,防止资源泄漏。
- 缓冲区刷新:每次写入记录后调用
Flush(),确保数据及时写入磁盘,而不是停留在Writer的缓冲区里。
内容的提问来源于stack exchange,提问作者Darara
相关产品推荐
相关产品推荐

