You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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())
	}
}

关键说明

  1. 区分不同的Writer:每个*csv.Writer都是独立的指针实例,只要你在初始化时分别传入不同的*os.File对象,它们就会对应各自的文件,操作不同的Writer自然会写入到对应的文件中。
  2. 锁的使用:我用defer mutex.Unlock()替代了手动在末尾解锁,这样即使函数中途panic,锁也能正常释放,避免死锁。
  3. 完善错误处理:每个文件操作(创建、Flush、Sync、Close)都添加了错误检查,还在创建第二个文件失败时关闭已打开的第一个文件,防止资源泄漏。
  4. 缓冲区刷新:每次写入记录后调用Flush(),确保数据及时写入磁盘,而不是停留在Writer的缓冲区里。

内容的提问来源于stack exchange,提问作者Darara

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.14 09:04:22