Go语言如何并发写入两个不同CSV文件?运行后仅生成文件无数据如何解决
问题根因
- select中的break无法跳出外层for循环
你代码里的break语句仅作用于select代码块,执行后仍会回到外层for循环继续执行,导致退出逻辑中的writer.Flush()、file.Close()永远不会被调用,缓冲区数据无法刷入磁盘。 - csv.Writer缓冲区未主动定期刷新
encoding/csv的Writer默认带有内存缓冲区,只有缓冲区满或者显式调用Flush()时才会将数据写入磁盘。你仅在退出逻辑中调用了Flush,程序正常运行过程中所有写入的数据都暂存在内存中,不会写入文件。 - 异常终止时退出逻辑不执行
你的main函数靠time.Sleep等待10分钟,如果你提前终止程序(比如按Ctrl+C),defer定义的Stop方法不会执行,QuitChan不会被关闭,退出逻辑永远不会触发。 - 额外说明:两个服务操作不同文件,不存在写入竞争,不需要加mutex,加了也无法解决当前问题。
修复方案
- 修正循环跳出逻辑,收到退出信号后直接return退出函数即可,不需要break:
case <-a.QuitChan: ticker.Stop() writer.Flush() // 可追加检查Flush错误:if err := writer.Error(); err != nil { fmt.Println(err) } file_one.Close() fmt.Println("Stopped recording.") return // 直接退出record函数
- 每次写入数据后主动Flush,保证数据及时写入磁盘:
err = writer.Write(header) if err != nil { fmt.Println(err) return } writer.Flush() // 写入表头后刷入磁盘 // 定时任务写入后也追加Flush err = writer.Write([]string{fmt.Sprintf("%2d:%2d:%2d", t.Hour(), t.Minute(), t.Second())}) if err != nil { fmt.Println(err) a.QuitChan <- struct{}{} } writer.Flush() // 写入行后刷入磁盘
- 增加系统信号监听,保证程序被手动终止时也能执行退出逻辑,替换main函数里的
time.Sleep(600*time.Second)即可:
// 需提前导入 os/signal、syscall 包 sigChan := make(chan os.Signal, 1) signal.Notify(sigChan, syscall.SIGINT, syscall.SIGTERM) <-sigChan // 阻塞到收到中断信号
内容的提问来源于stack exchange,提问作者Paul Côté
相关产品推荐
相关产品推荐

