等待所有的例程完成

roy*_*e41 0 concurrency go goroutine

第一次与go,并试图开始惯例和WaitGroups工作.

我有一个包含100行数据的CSV文件.(101包括标题)

我有以下简单的代码:

package main

import (
    "bufio"
    "fmt"
    "io"
    "os"
    "sync"
    "time"
)

func main() {
    start := time.Now()
    numRows := 0

    waitGroup := sync.WaitGroup{}
    file, _ := os.Open("./data.csv")

    scanner := bufio.NewScanner(file)
    scanner.Scan() // to read the header

    for scanner.Scan() {
        err := scanner.Err()

        if err != nil && err != io.EOF {
            panic(err)
        }

        waitGroup.Add(1)

        go (func() {
            numRows++
            waitGroup.Done()
        })()
    }

    waitGroup.Wait()
    file.Close()

    fmt.Println("Finished parsing ", numRows)
    fmt.Println("Elapsed time in seconds: ", time.Now().Sub(start))
}
Run Code Online (Sandbox Code Playgroud)

当我运行它时,numRows输出每次在94到100之间波动.我希望每次都是100.如果我在10行数据的CSV上运行相同的代码,它会10每次输出.

在我看来,最后几个例行程序没有及时完成.

我尝试了以下失败的方法:

  • 用a CsvReader而不是aScanner
  • 移动waitGroup.Add(1)到匿名函数下面
  • 将匿名函数移动到包级别范围函数中(并使用ptrs传递事物)

我错过了什么?

Fli*_*mzy 7

在不同的goroutine中同时修改单个变量是不安全的.您的某些更新numRows将丢失,有时您的程序可能会崩溃.

使用numRows互斥锁保护变量,或使用其中一个原子函数以原子方式添加变量:

var numRows int32

// ...

    go (func() {
        atomic.AddInt32(&numRows, 1)
        waitGroup.Done()
    })()
Run Code Online (Sandbox Code Playgroud)