GO канал и предотвращение тупиковой ситуации (лучшее решение, чем чтение всех каналов) - PullRequest
0 голосов
/ 28 ноября 2018

У меня есть базовый канал, в который я ввожу число. Позже он изменяет себя по формуле. Есть 3 канала, которые могут принимать значения в разных случаях. Среднее число отправленных номеров должно быть между двумя значениями, как видно нацикл if

if average < 10 {
        channel <- average
    }
    if average > 0 && average < 100 {
        channel1 <- average
    }
    if average > 75 && average < 200 {
        channel2 <- average
    }

Проблема, с которой я сталкиваюсь, заключается в том, чтобы избежать ситуации взаимоблокировки. Я должен сделать странный цикл if, который читает все значения, которые были отправлены, но никогда не читает

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

Так что можно избежать странных циклови есть лучшее решение для этого.

package main

import(
    "fmt"
    "sync"
) 

var wait sync.WaitGroup
var averageIsOk = true
var doneSendersCount = 0
var counterIsDone = false

func main() {
    counterChannel := make(chan float64)
    channel := make(chan float64)
    channel1 := make(chan float64)
    channel2 := make(chan float64)

    for i := 0; i < 10; i++ {
        wait.Add(1)
        go send(counterChannel, float64(i))
    }

    wait.Add(1)
    go count(counterChannel, channel, channel1, channel2)

    wait.Add(1)
    go print(channel, 1)

    wait.Add(1)
    go print(channel1, 2)

    wait.Add(1)
    go print(channel2, 3)

    wait.Wait()
}

func send (counterChannel chan<- float64, startNumber float64){
    defer wait.Done()
    i := startNumber

    for averageIsOk {
        counterChannel <- i
        i = i * i - 4 * i + 1
    }

    doneSendersCount++
}

func count (counterChannel <-chan float64, channel chan<- float64, channel1 chan<- float64, channel2 chan<- float64){
    defer wait.Done()

    var averageArray [15]float64
    for i := 0; i < 15; i++ {
        averageArray[i] = 0
        }

    for averageIsOk {
        receivedNumber := <- counterChannel

        for i := 14; i > 0; i-- {
            averageArray[i] = averageArray[i - 1]
        }

        averageArray[0] = receivedNumber

        average := 0.0
        for i := 0; i < 15; i++ {
            average += averageArray[i]
        }
        average = average / 15

        if average < 10 {
            channel <- average
        }
        if average > 0 && average < 100 {
            channel1 <- average
        }
        if average > 75 && average < 200 {
            channel2 <- average
        }

        if average > 200 {

            close(channel)
            close(channel1)
            close(channel2)
            averageIsOk = false
        }
    }

    counterIsDone = true
    for doneSendersCount != 10 {
        select {
        case <- counterChannel:
            break
        default:
            break
        }
    }
}

func print (printChannel <-chan float64, printerNumber int){
    defer wait.Done()

    for averageIsOk {
        receivedNumber := <- printChannel
        fmt.Println("Kanalas nr-", printerNumber, ":", receivedNumber)
    }

    for !counterIsDone {
        select {
        case <- printChannel:
            break
        default:
            break
        }
    }
}
...