Чтение нескольких каналов из канала дает неверный счетчик данных - PullRequest
0 голосов
/ 01 января 2019

Я работаю над программой, в которой я читаю CSV-файл и выполняю следующие операции:

Полный код доступен по адресу: Здесь

Мой CSV-файлдоступно по адресу: CSV-файл

Проблема в том, что иногда я получаю правильный счет для A и B, а иногда я получаю неправильный счет.

Я думаю, что делаючто-то не так в Goroutines и каналах связи.

Когда я комментирую 2-ую программу, я получаю правильный результат 1-й Goutoutine.Но когда я раскомментирую 2-й Goroutine, я получаю неправильные выходные данные Goroutine 1 и 2.

Кто-нибудь может объяснить, пожалуйста, что я делаю неправильно?

Также, когда я запускаю run -race main., результат показывает мне состояние гонки.

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!")
}

1 Ответ

0 голосов
/ 01 января 2019

В обоих случаях ваш wg.Done () вызывается сразу после запуска программы.Это означает, что ваша группа WaitGroup не ожидает завершения процедуры.Помните, что процесс вызова продолжается, когда вы вызываете программу.Попробуйте положить вызов wg.Done () в процедуру, когда она закончит делать.

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

ИЛИ

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