从一个通道读取的多个goroutine给出了错误的数据计数

从一个通道读取的多个goroutine给出了错误的数据计数,go,concurrency,goroutine,Go,Concurrency,Goroutine,我正在编写一个程序,读取csv文件并执行以下操作: 完整代码可从以下网址获得: 我的CSV文件位于: 问题是有时我得到A和B的正确计数,有时我得到错误计数 我想我在Goroutines和Channel communication方面做错了什么 当我评论第二个goroutine时,我得到了第一个goroutine的正确结果。但是当我取消注释第二个Goroutine时,我得到了goroutine1和2的错误输出 谁能解释一下我做错了什么 另外,当我运行run-race main.go时,结果会显示

我正在编写一个程序,读取csv文件并执行以下操作:

完整代码可从以下网址获得:

我的CSV文件位于:

问题是有时我得到A和B的正确计数,有时我得到错误计数

我想我在Goroutines和Channel communication方面做错了什么

当我评论第二个goroutine时,我得到了第一个goroutine的正确结果。但是当我取消注释第二个Goroutine时,我得到了goroutine1和2的错误输出

谁能解释一下我做错了什么

另外,当我运行run-race main.go时,结果会显示一个比赛状态

func main() {
    input, err := os.Open("CSV.csv")
    if err != nil {
        fmt.Println("Error while opening CSV file.")
        return
    }
    defer input.Close()

    formattedStartDateRange,err := time.Parse(time.RFC3339, startDateRange)
    if err != nil {
        fmt.Println(err)
    }

    formattedendDateRange,err := time.Parse(time.RFC3339, endDateRange)
    if err != nil {
        fmt.Println(err)
    }

    reader := csv.NewReader(input)
    reader.FieldsPerRecord = -1
    files := make(map[string]chan []string)

    wg := &sync.WaitGroup{}

    var line []string
    for line, err = reader.Read(); err == nil; line, err = reader.Read() {
        ch, ok := files[line[0]]
        if ok {
            ch <- line
        } else {
            ch = make(chan []string, 8)
            ch <- line
            wg.Add(2) // Must wait for 2 calls to 'done' before moving on

            go func() {
                UserMapMutex.Lock()
                if (findNumberOfBuilds(formattedStartDateRange, formattedendDateRange, ch, wg)) {
                    totalBuildCount++
                }
                UserMapMutex.Unlock()
                wg.Done()
            }()

            go func() {
                UserMapMutex.Lock()
                countUserBuildFrequency(ch, wg)
                UserMapMutex.Unlock()
                wg.Done()
            }()


            files[line[0]] = ch
        }
    }


    if err.Error() != "EOF" {
        fmt.Println("Error while reading CSV file.")
        return
    }
    for _, ch := range files {
        close(ch)
    }
    wg.Wait()

    fmt.Println("Total Build executed from 1st November to 30th November =", totalBuildCount)
    fmt.Println("Total Build", userBuildFreq["5c00a8f685db9ec46dbc13d7"])
    fmt.Println("Done!")
}
func main(){
输入,错误:=os.Open(“CSV.CSV”)
如果错误!=零{
fmt.Println(“打开CSV文件时出错”)
回来
}
延迟输入。关闭()
FormattedStartDaterRange,错误:=time.Parse(time.RFC3339,StartDaterRange)
如果错误!=零{
fmt.Println(错误)
}
formattedendDateRange,错误:=time.Parse(time.rfc339,endDateRange)
如果错误!=零{
fmt.Println(错误)
}
读卡器:=csv.NewReader(输入)
reader.FieldsPerRecord=-1
文件:=make(映射[string]chan[]string)
wg:=&sync.WaitGroup{}
变量行[]字符串
对于行,err=reader.Read();err==nil;行,err=reader.Read(){
ch,ok:=文件[第[0]行]
如果可以的话{

ch在这两种情况下,您的wg.Done()都会在启动goroutine后立即被调用。这意味着您的WaitGroup不会等待goroutine完成。请记住,调用goroutine时调用过程会继续。在goroutine完成工作后,尝试将wg.Done()调用放入goroutine中

go func(wg) {
    // do stuff
    wg.Done
}


所有问题都必须完整,无需跟随链接。这意味着您必须在问题中包含代码和CSV文件的一部分。当然,欢迎提供指向更大版本的链接,但关键是问题本身必须完整,以防链接在将来消失。此代码非常奇怪。对于每一行,您都创建一个goroutine,将一行写入一个通道,然后goroutine调用一个函数,该函数以某种方式使用该通道,但未显示。这a)意味着函数调用可能使用也可能不使用刚刚插入的行-您可能应该只传递该行而不使用该通道;b)意味着如果其中一个函数读取value从通道,另一个将不能,因为这将是发送的两倍;和c)您运行两个goroutine,这两个goroutine都是完全锁定的,所以您最好只使用一个。正确!您提到的B选项就是我正在做的。我也这样做了,只使用了一个goroutine。但是有一个疑问,我们如何实现正确的result当我们有两个goroutine时?我知道如果一个goroutine从通道读取,那么另一个将无法读取。有什么方法可以做到吗?我已经更新了代码,正如您在下面的链接中所说,但仍然无法实现。当我注释第二个goroutine时,我得到了第一个goroutine的正确结果。但是当我取消注释第二个goroutine时ine,我得到的Goroutine 1和2的输出都不正确。所以我认为是第二个Goroutine造成了混乱。你有什么新发现吗?
go func(wg) {
    defer wg.Done
    // do stuff
}