百度360必应搜狗淘宝本站头条
当前位置:网站首页 > IT知识 > 正文

【Go】用 Go 语言并发处理 CSV 文件到数据库

liuian 2025-03-04 13:04 33 浏览

通过并发处理,我们能够大大提升 CSV 文件迁移到数据库的速度。Go 的 goroutines 和通道非常适合这种类型的任务,可以高效地处理 I/O 密集型的操作。

问题背景

假设你拥有一个包含大量联系人信息的 CSV 文件,需要将这些信息迁移到数据库中。这些联系人信息可能包含姓名、电话号码、邮箱地址等。如果使用传统的单线程方式,逐条处理数据,迁移过程可能会非常缓慢,尤其是在数据量很大时。

在处理大量的 CSV 文件数据并迁移到数据库时,使用并发可以显著提升处理效率。Go 语言的 goroutine 和通道(channel)非常适合用来并发地处理数据。

下面我将给出一个示例,展示如何使用 Go 语言并发地处理 CSV 文件,并将数据插入到数据库中。

主要思路

  1. 读取 CSV 文件:使用 encoding/csv 包来解析 CSV 文件。
  2. 并发处理数据:将 CSV 文件的数据分批次发送到多个 goroutine 中进行并发处理。
  3. 数据库插入:每个 goroutine 从通道中接收数据并将其插入到数据库中。
  4. 同步控制:使用 sync.WaitGroup 来等待所有 goroutine 完成任务。

假设我们的数据库是 MySQL,使用 github.com/jinzhu/gorm 作为 ORM 库来处理数据库插入。我们会定义一个 Contact 结构体来映射数据库中的表,并用并发的方式将每一行 CSV 数据插入到数据库。

示例代码

1. 安装必要的依赖

首先,你需要安装 gorm 和 csv 相关的包:

go get github.com/jinzhu/gorm
go get github.com/jinzhu/gorm/dialects/mysql
go get encoding/csv1.2.3.

2. 数据库模型定义

我们先定义一个 Contact 结构体,它会对应数据库中的联系人表。

package main

import (
	"github.com/jinzhu/gorm"
	_ "github.com/jinzhu/gorm/dialects/mysql"
	"fmt"
)

// Contact 是数据库中表的模型
type Contact struct {
	ID        uint   `gorm:"primary_key"`
	Name      string `gorm:"size:255"`
	Phone     string `gorm:"size:255"`
	Email     string `gorm:"size:255"`
}

func initDB() (*gorm.DB, error) {
	// 使用 MySQL 数据库
	db, err := gorm.Open("mysql", "user:password@/dbname?charset=utf8&parseTime=True&loc=Local")
	if err != nil {
		return nil, err
	}

	// 自动迁移表结构
	db.AutoMigrate(&Contact{})
	return db, nil
}

3. 读取 CSV 文件并处理

接下来,我们需要读取 CSV 文件并将每一行数据并发地插入到数据库中。

package main

import (
	"encoding/csv"
	"fmt"
	"os"
	"strings"
	"sync"
)

// 处理 CSV 文件并将数据插入数据库
func processCSV(filePath string, db *gorm.DB) error {
	// 打开 CSV 文件
	file, err := os.Open(filePath)
	if err != nil {
		return err
	}
	defer file.Close()

	// 创建 CSV 阅读器
	reader := csv.NewReader(file)

	// 读取所有行
	records, err := reader.ReadAll()
	if err != nil {
		return err
	}

	// 使用 WaitGroup 来同步所有的 goroutine
	var wg sync.WaitGroup

	// 通道用于发送每行数据
	ch := make(chan Contact, len(records))

	// 启动多个 goroutine 来并发处理 CSV 数据
	for i := 1; i < len(records); i++ { // 从 1 开始,跳过标题行
		wg.Add(1)
		go func(record []string) {
			defer wg.Done()
			// 将 CSV 行转换为 Contact 实例
			contact := Contact{
				Name:  record[0],
				Phone: record[1],
				Email: record[2],
			}
			ch <- contact // 发送数据到通道
		}(records[i])
	}

	// 启动一个 goroutine 来将通道中的数据插入到数据库
	go func() {
		for contact := range ch {
			if err := db.Create(&contact).Error; err != nil {
				fmt.Println("Error inserting record:", err)
			}
		}
	}()

	// 等待所有 goroutine 完成
	wg.Wait()

	// 关闭通道
	close(ch)

	return nil
}

func main() {
	// 初始化数据库
	db, err := initDB()
	if err != nil {
		fmt.Println("Failed to connect to database:", err)
		return
	}
	defer db.Close()

	// 处理 CSV 文件并将数据迁移到数据库
	err = processCSV("contacts.csv", db)
	if err != nil {
		fmt.Println("Error processing CSV file:", err)
		return
	}

	fmt.Println("CSV data successfully migrated to the database.")
}

4. 代码说明

①.初始化数据库:

  • initDB 函数用于初始化 MySQL 数据库连接并进行自动迁移。
  • 我们使用 gorm 来处理数据库操作,模型 Contact 映射到数据库中的 contacts 表。

②.读取 CSV 文件:

  • processCSV 函数打开并读取 CSV 文件。然后,它读取所有的记录,并将每条记录通过 goroutine 异步发送到通道中。
  • 每个 goroutine 都会将一条记录从 CSV 转换为 Contact 对象,并将其发送到通道。

③.并发处理数据:

  • sync.WaitGroup 被用来确保所有的 goroutine 完成任务。wg.Add(1) 在启动每个 goroutine 时调用,wg.Done() 在每个 goroutine 完成时调用。
  • 使用 chan Contact 通道来将数据从多个 goroutine 传递到数据库插入部分。一个单独的 goroutine 从通道中接收数据并将其插入到数据库。

④.并发插入数据库:

  • 每个 goroutine 向通道发送数据,然后另一个 goroutine 从通道中读取数据并将其插入数据库。通过这种方式,多个数据库插入操作是并发进行的。

⑤.关闭通道与等待:

  • 在所有数据都发送到通道后,使用 wg.Wait() 等待所有 goroutine 完成处理。
  • 关闭通道以确保数据库插入操作可以顺利结束。

5. 性能优化

在这个例子中,我们并发地读取 CSV 文件并将数据插入数据库,显著提高了处理速度。但是,对于大型数据集,还可以做更多的性能优化:

  • 批量插入:可以将多个数据条目批量插入数据库,而不是每次插入一条记录。批量插入可以显著减少数据库的 I/O 操作,提升性能。
  • 控制并发数:通过 semacphore 或者限制通道缓冲区大小,可以控制并发数,避免数据库被过多并发请求压垮。
  • 数据库连接池:确保数据库连接池的配置合理,避免过多的并发连接造成数据库连接耗尽。

总结

通过并发处理,我们能够大大提升 CSV 文件迁移到数据库的速度。Go 的 goroutines 和通道非常适合这种类型的任务,可以高效地处理 I/O 密集型的操作。

在处理大型 CSV 文件时,使用并发处理可以显著提升性能,减少总体处理时间。


相关推荐

大地影视中文第二页的背景故事

大地影院通常会有明显的入口标识,你可以根据影院外部的建筑结构和指示牌来找到入口。一般来说,大地影院的入口可能位于建筑的主立面或者侧面,有时也可能位于地下停车场或者商场内部。当你到达影院所在的建筑时,可...

win10共享打印机需要密码(win10共享打印机需要密码吗)

共享打印机需要输入用户名和密码,该如何操作,下面给大家来介绍下。1、首先打开电脑的控制面板,点击管理工具。2、然后在打开的管理工具窗口中,点击本地安全策略。3、接着在打开的页面中,点击本地策略。4、然...

系统引导启动项怎么设置(系统引导按哪个键)

如果您想在计算机启动时添加系统启动引导选项,可以按照以下步骤进行操作:1.打开“运行”窗口,可以通过快捷键Win+R打开“运行”窗口。2.在“运行”窗口中输入“msconfig”命令,并点击“...

win10录屏快捷键ctrl+alt+(win10录屏功能快捷键)

答,笔记本电脑录屏快捷键是ctrl+alt+s。绝大多数人录制屏幕时,第一个想到的就是电脑自带的录屏功能,比较的方便快捷。这种方法运用起来时非常简单的,只需在键盘上同时按下“ctrl+alt+s”键就...

壁纸下载(壁纸下载安装)

回答如下:要下载电视屏保相册,您需要先找到适用于您的电视的屏保应用程序。这些应用程序可能会根据您的电视品牌和型号而有所不同,您可以在电视的应用商店中搜索或查看电视制造商的网站以获取更多信息。一旦您找到...

木马病毒下载安装(木马病毒下载安装不实名认证)

现在1,你自己机器上下载个杀毒软件,安装之后不要删除安装包2,运行杀毒软件3,插入优盘,杀毒软件会自动扫描优盘发现病毒然后提示你4,选择处理/杀毒/清理这些字样5,把杀毒软件安装包复制到优盘6,右键优...

免费清理软件哪个最好最快(免费好用的清理垃圾软件)
  • 免费清理软件哪个最好最快(免费好用的清理垃圾软件)
  • 免费清理软件哪个最好最快(免费好用的清理垃圾软件)
  • 免费清理软件哪个最好最快(免费好用的清理垃圾软件)
  • 免费清理软件哪个最好最快(免费好用的清理垃圾软件)
手机cdr转jpg最简单的方法(手机cdr转换jpg)

cdr文件怎么转换成jpg,快来看下操作方法吧。方法/步骤1、打开电脑中的cdr软件,点击文件,打开,打开需要转换格式的cdr文件。2、点击菜单栏的文件,导出。3、打开导出对话框选择保存文件路径。4、...

xp永久激活工具(xp永久激活码)

如果你需要重置XP的激活器,你需要先打开“开始”菜单,然后选择“运行”。在运行对话框中,输入“regedit”,然后按回车键。这会打开注册表编辑器。在编辑器中,使用左侧面板来导航到“HKEY_LOCA...

cad2008激活序列号(激活cad的序列号)

1.首先运行“AutoCAD2008安装包”中的“Setup.exe”安装AutoCAD2008,安装过程需要十分钟左右;2.第一次运行AutoCAD2008时,请在注册界面输入序列号666-9...

自己可以重装电脑系统么(可以自己重装系统吗)

电脑自身也可以重装系统。1.电脑是一个可编程的设备,通过特定的步骤和操作,用户可以自行进行系统重装。2.重装系统的过程包括备份重要数据、获取系统安装介质、重新启动电脑进入安装界面、按照指引选择系统...

win11免费下载(win11正式版下载)
  • win11免费下载(win11正式版下载)
  • win11免费下载(win11正式版下载)
  • win11免费下载(win11正式版下载)
  • win11免费下载(win11正式版下载)
qq邮箱在哪里找账号(qq邮箱账号在qq里怎么找)
  • qq邮箱在哪里找账号(qq邮箱账号在qq里怎么找)
  • qq邮箱在哪里找账号(qq邮箱账号在qq里怎么找)
  • qq邮箱在哪里找账号(qq邮箱账号在qq里怎么找)
  • qq邮箱在哪里找账号(qq邮箱账号在qq里怎么找)
苹果处理器性能排行(苹果处理器性能排行榜平板)

1、截止至最新的iPhoneXS上搭载的A12,从iPhone4首次搭载A4处理器开始,目前已经有9代的苹果A系列处理器;2、A4是一颗45nm制程的ARMCortex-A8的单核心处理器,GP...

苹果手机怎么录屏(苹果手机怎么录屏在哪里打开)

iPhone手机的屏幕录制功能需要在设置里面进行添加,添加成功之后,就可以使用录屏功能了。点击控制中心进入iPhone手机的设置,来到设置之后,找到控制中心选项并点击。点击加号添加录屏功能来到控制中心...