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