Go 处理文件行的有效方法

Go 处理文件行的有效方法,go,concurrency,Go,Concurrency,我试图学习一些围棋,我试图制作一个脚本,从csv文件读取,做一些处理,并取得一些结果 我遵循一种管道模式,这样一个goroutine使用scanner每行读取一个文件,将行发送到通道,不同的goroutine使用通道内容 我正在尝试做的一个例子: 我的问题是:在csv文件中有很多记录。我想在结果线之间做一些数学运算。假设record1是r1,record2是r2,依此类推 当我读取文件时,我有r1。在下一个扫描仪循环中,我有r2。我想看看r1-r2对我来说是否有效。如果是的话,在他们之间做一些

我试图学习一些围棋,我试图制作一个脚本,从csv文件读取,做一些处理,并取得一些结果

我遵循一种管道模式,这样一个goroutine使用scanner每行读取一个文件,将行发送到通道,不同的goroutine使用通道内容

我正在尝试做的一个例子:

我的问题是:在csv文件中有很多记录。我想在结果线之间做一些数学运算。假设record1是r1,record2是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)这不是一个简单的操作,需要很长时间。谢谢你的回复。所以你的建议是在从文件中读取数据时过滤数据,并将过滤后的内容发送到频道。这也是我的猜测。你编写的代码分别检查每一行,但事实并非如此。我很难想出如何在两行之间进行检查你的帖子真的很有帮助!如果这个回复解决了你的问题-你可以将它标记为“有用”和“回答”: