Go 中 CSV 和地图的性能不佳

我需要编写一个 Go 脚本来打开一个大的 CSV 文件,并根据每行第一个元素的值创建新的、单独的 CSV。


CSV 文件如下所示:


"country", "otherfield", "otherfield1", "otherfield2", "etc"

"AT", "otherfield", "otherfield1", "otherfield2", "etc"

"AT", "otherfield", "otherfield1", "otherfield2", "etc"

"DE", "otherfield", "otherfield1", "otherfield2", "etc"

"DE", "otherfield", "otherfield1", "otherfield2", "etc"

所以,我想要做的是创建一个文件AT.csv,其中包含第一个字段的值(例如),其中包含以该值开头的所有行。

我目前遇到的问题是表演很慢。我什至有一个用 PHP 编写的类似脚本,它以比这更快的方式执行相同的操作。这显然让我觉得我的 Go 脚本肯定有问题。

有人可以帮助我了解它有什么问题吗?


拉莫斯之舞
浏览 208回答 2
2回答

红颜莎娜

我支持@plusmid 的回答——你的程序大部分时间都花在打开/(覆盖)写入/关闭文件上。所以,首先修复这个bug,每个key只写一次内容:package mainimport (    "encoding/csv"    "fmt"    "os")func main() {    // contentCreated := make(chan map[string]string)    createContent("union_exp.csv")}func createContent(csvfilename string) {    keys := ""    content := make(map[string]string)    csvfile, err := os.Open(csvfilename)    if err != nil {        fmt.Println(err)    }    defer csvfile.Close()    reader := csv.NewReader(csvfile)    reader.FieldsPerRecord = -1    rawCSVdata, err := reader.ReadAll()    if err != nil {        fmt.Println(err)        os.Exit(1)    }    for i, each := range rawCSVdata {        if i == 0 {            keys = "\"" + each[0] + "\",\"" + each[1] + "\",\"" + each[2] + "\",\"" + each[3] + "\",\"" + each[4] + "\"\n"        } else {            stringtoadd := "\"" + each[0] + "\",\"" + each[1] + "\",\"" + each[2] + "\",\"" + each[3] + "\",\"" + each[4] + "\"\n"            if i%10000 == 0 {                fmt.Println(i)            }            exists := Exists(content, each[0])            if !exists {                content[each[0]] = keys            }            content[each[0]] += stringtoadd        }    }    for key, content := range content {        createFile(key, content)    }}func createFile(name, content string) {    f, _ := os.Create(name + ".csv")    f.WriteString(content)    f.Close()}func Exists(content map[string]string, name string) bool {    _, exists := content[name]    return exists}在 25k CSV 上,它给了我 50 -> 5 秒的速度提升。接下来考虑使用goroutines并行解析文件。现在您只使用单核。此外,还有一些问题,例如使用 + 运算符连接字符串,这通常比 fmt.Sprintf() 慢。您有很多空间可以在这里优化代码。
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Go