Как получить все результаты без получения тупиковой ошибки - PullRequest
0 голосов
/ 23 сентября 2019

Должен получить все значения из среза без тупика в конце.Я не получаю тупиковую ошибку, когда я не использую waitGroups. <- time.After (time.Second) </em> Это то, что я использовал вместо waitGroup, и это помогло

package main

import (
    "fmt"
    "sync"
)

var wg sync.WaitGroup

func main() {
    c := make(chan int)

    a := []int{1, 3, 10, 8, 15, 23}

    wg.Add(len(a))

    go func(i []int) {
        for _, v := range i {
            c <- v
        }
    }(a)

    go Print(c)
    wg.Wait()
}

func Print(c chan int) {
    for v := range c {
        fmt.Println(v)
    }
    wg.Done()
    close(c)
}

1 Ответ

2 голосов
/ 23 сентября 2019

вы запутались в механизме синхронизации.Дело в том, чтобы синхронизировать асинхронные рабочие.Не количество элементов, которые они будут обрабатывать.

Вы не закрываете канал после завершения записи, а после того, как предполагается, что чтение завершено.Это неправильно.

Вы выполняете асинхронную проверку как производителя, так и потребителя.Это немного странно.Поскольку у вас уже есть поток в main, вы можете воспользоваться им, чтобы не запускать ложную подпрограмму.

некоторые варианты вашего кода после исправлений

package main

import (
    "fmt"
    "sync"
)

var wg sync.WaitGroup

func main() {
    c := make(chan int)

    a := []int{1, 3, 10, 8, 15, 23}

    wg.Add(1) // one async worker
    go Print(c) // ensure the worker is started upfront

    for _, v := range a {
        c <- v // write the data
    }
    close(c) //then close

    wg.Wait()
    fmt.Println("done")
}

func Print(c chan int) {
    for v := range c { // the loop will break because the channel is closed.
        fmt.Println(v)
    }
    wg.Done()
}

Вы также можете создать его безлюбая группа ожидания.

package main

import (
    "fmt"
)

func main() {
    c := make(chan int)

    a := []int{1, 3, 10, 8, 15, 23}

    go func() {
        for _, v := range a {
            c <- v // write the data
        }
        close(c) //then close
    }()

    for v := range c { // the loop will break because the channel is closed.
        fmt.Println(v)
    }
    fmt.Println("done")
}
...