Go 处理文件行的有效方法
我试图学习一些围棋,我试图制作一个脚本,从csv文件读取,做一些处理,并取得一些结果 我遵循一种管道模式,这样一个goroutine使用scanner每行读取一个文件,将行发送到通道,不同的goroutine使用通道内容 我正在尝试做的一个例子: 我的问题是:在csv文件中有很多记录。我想在结果线之间做一些数学运算。假设record1是r1,record2是r2,依此类推 当我读取文件时,我有Go 处理文件行的有效方法,go,concurrency,Go,Concurrency,我试图学习一些围棋,我试图制作一个脚本,从csv文件读取,做一些处理,并取得一些结果 我遵循一种管道模式,这样一个goroutine使用scanner每行读取一个文件,将行发送到通道,不同的goroutine使用通道内容 我正在尝试做的一个例子: 我的问题是:在csv文件中有很多记录。我想在结果线之间做一些数学运算。假设record1是r1,record2是r2,依此类推 当我读取文件时,我有r1。在下一个扫描仪循环中,我有r2。我想看看r1-r2对我来说是否有效。如果是的话,在他们之间做一些
r1
。在下一个扫描仪循环中,我有r2
。我想看看r1-r2
对我来说是否有效。如果是的话,在他们之间做一些数学运算。然后用同样的方法检查r3
r4
。如果r1-r2
无效,则不必关心r2
并执行r1-r3
等操作
在我将文件行放入频道并处理频道内容后,我在读取文件时是否应该处理此问题
任何不会破坏并发性的建议?我认为您应该确定
中的“r1-r2是否对您有效”将行读入工作队列功能
所以,当您没有有效数字对时,您应该读取当前行,并逐个读取下一行。当您得到它时,您将在workQueue
频道内发送这对,并搜索下一对
这是带有更改的代码:
package main
import (
"bufio"
"log"
"os"
"errors"
)
var concurrency = 100
type Pair struct {
line1 string
line2 string
}
func main() {
// It will be better to receive file-path from somewhere (like args or something like this)
filePath := "/path/to/file.csv"
// This channel has no buffer, so it only accepts input when something is ready
// to take it out. This keeps the reading from getting ahead of the writers.
workQueue := make(chan Pair)
// We need to know when everyone is done so we can exit.
complete := make(chan bool)
// Read the lines into the work queue.
go func() {
file, e := os.Open(filePath)
if e != nil {
log.Fatal(e)
}
// Close when the function returns
defer file.Close()
scanner := bufio.NewScanner(file)
// Get pairs and send them into "workQueue" channel
for {
line1, e := getNextCorrectLine(scanner)
if e != nil {
break
}
line2, e := getNextCorrectLine(scanner)
if e != nil {
break
}
workQueue <- Pair{line1, line2}
}
// Close the channel so everyone reading from it knows we're done.
close(workQueue)
}()
// Now read them all off, concurrently.
for i := 0; i < concurrency; i++ {
go startWorking(workQueue, complete)
}
// Wait for everyone to finish.
for i := 0; i < concurrency; i++ {
<-complete
}
}
func getNextCorrectLine(scanner *bufio.Scanner) (string, error) {
var line string
for scanner.Scan() {
line = scanner.Text()
if isCorrect(line) {
return line, nil
}
}
return "", errors.New("no more lines")
}
func isCorrect(str string) bool {
// Make your validation here
return true
}
func startWorking(pairs <-chan Pair, complete chan<- bool) {
for pair := range pairs {
doTheWork(pair)
}
// Let the main process know we're done.
complete <- true
}
func doTheWork(pair Pair) {
// Do the work with the pair
}
主程序包
进口(
“布菲奥”
“日志”
“操作系统”
“错误”
)
var并发=100
类型对结构{
第1行字符串
第2行字符串
}
func main(){
//最好从某处接收文件路径(如args或类似的内容)
文件路径:=“/path/to/file.csv”
//此通道没有缓冲区,因此它仅在准备就绪时接受输入
//把它拿出来。这样可以防止阅读超过作者。
工作队列:=制造(成双)
//我们需要知道每个人什么时候都完成了,这样我们才能退出。
完成:=制造(陈布尔)
//将这些行读入工作队列。
go func(){
文件,e:=os.Open(文件路径)
如果e!=nil{
日志。致命(e)
}
//函数返回时关闭
延迟文件。关闭()
扫描程序:=bufio.NewScanner(文件)
//获取对并将其发送到“工作队列”通道
为了{
第1行,e:=getNextCorrectLine(扫描仪)
如果e!=nil{
打破
}
第2行,e:=getNextCorrectLine(扫描仪)
如果e!=nil{
打破
}
workQueue您不应该直接跳入并发解决方案,尤其是在处理从文件读取的数据时,比如从文件(或网络)读取可能是您应用程序的瓶颈,您可能无法从并发处理部分中获得任何好处,相反,您甚至可以同时使其变得更慢、更复杂。是的,但如果使用行执行工作,并发解决方案是有意义的(从link到github)这不是一个简单的操作,需要很长时间。谢谢你的回复。所以你的建议是在从文件中读取数据时过滤数据,并将过滤后的内容发送到频道。这也是我的猜测。你编写的代码分别检查每一行,但事实并非如此。我很难想出如何在两行之间进行检查你的帖子真的很有帮助!如果这个回复解决了你的问题-你可以将它标记为“有用”和“回答”: