Golang выпуск каналов - PullRequest
       51

Golang выпуск каналов

0 голосов
/ 10 апреля 2020

У меня есть простой пример с каналами: https://play.golang.org/p/eLcpzXeCHms

package main

import (
    "fmt"
)

func execute(trueChan chan<- bool, lowerRange int32, upperRange int32) {
    for lowerRange <= upperRange {
        fmt.Printf("\nhandling number %v", lowerRange)
        if lowerRange%2 == 0 {
            go func() {
                trueChan <- true
            }()
        }
        lowerRange++
    }
    close(trueChan)
}

func main() {
    counter := 0

    trueChan := make(chan bool)

    execute(trueChan, 5, 25)

    for {
        if _, ok := <-trueChan; ok {
            counter++
        } else {
            break
        }
    }

    fmt.Printf("\n%v", counter)
}

Первая проблема: иногда я получаю сообщение об ошибке ...

handling number 5
handling number 6
handling number 7
handling number 8
handling number 9
handling number 10
handling number 11
handling number 12
handling number 13
handling number 14
handling number 15
handling number 16
handling number 17
handling number 18
handling number 19
handling number 20
handling number 21
handling number 22
handling number 23
handling number 24
handling number 25
0
panic: send on closed channel

И вторая проблема - мой счетчик всегда равен 0.

Может кто-нибудь дать мне подсказку, что я делаю не так?

Ответы [ 2 ]

2 голосов
/ 10 апреля 2020

Ваш код:

  1. Создает небуферизованный канал trueChan.
  2. Создает 10 процедур, каждая из которых будет пытаться записать в trueChan, которые будут блокироваться до чего-то читает из него.
  3. Закрывает trueChan, затем возвращается к main()
  4. main() печатает 0, поскольку он еще ничего не прочитал из goroutines
  5. Между тем, поскольку trueChan было закрыто на шаге 3, до того, как с ним будут выполнены процедуры, первая процедура, пытающаяся записать в канал панику

Как минимум, вы не должны закрывать trueChan до тех пор, пока вы не узнаете, что все операции с ним завершены. На практике вы закрываете его еще до того, как они начинают его использовать.

A sync.WaitGroup может быть одним из способов сделать это, но не очевидно, как это сделать в вашем код, так как я не совсем уверен в вашей цели. Этот код выглядит как простое упражнение, а не как пример из реальной жизни. Если вы можете объяснить свою цель, я, вероятно, могу предложить более конкретную c рекомендацию.

1 голос
/ 10 апреля 2020

Ваша первая и вторая проблемы совпадают root:
Вы закрываете канал в основной процедуре , программа закрывает канал, выходит из программы до того, как ваша процедура отправит данные в канал
Вы должны обычно закрывать канал в отсрочку процедуры go, которая использует этот канал. Например, и исправление для вашего кода:

package main

import (
    "fmt"
)

func execute(trueChan chan<- bool, lowerRange int32, upperRange int32) {
    go func() {
        defer func(){
            close (trueChan)
        }()
        for lowerRange <= upperRange {
            fmt.Printf("\n handling number %v", lowerRange)
            if lowerRange%2 == 0 {
                trueChan <- true
            }
            lowerRange++
        }

    }()
}

func main() {
    counter := 0

    trueChan := make(chan bool)

    execute(trueChan, 5, 25)

    for _ = range trueChan{ // For small improvement here. Ref as below 
            counter++
    }

    fmt.Printf("\n%v", counter)
}

https://tour.golang.org/concurrency/4

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...