2017-10-01 18 views
0

J'essaie le modèle fan in - fan out avec un problème factoriel. Mais je reçois:Obtenir l'impasse pendant que j'essaie d'émuler le ventilateur - ventiler avec des calculs factoriels

fatal error: all goroutines are asleep - deadlock! 

et incapable d'identifier la raison de l'interblocage. J'essaie de calculer simultanément un factoriel pour 100 nombres en utilisant le modèle de fan-in fan-out.

package main 

import (
    "fmt" 
) 

func main() { 
    _inChannel := _inListener(generator()) 
    for val := range _inChannel { 
     fmt.Print(val, " -- ") 
    } 
} 

func generator() chan int { // NEED TO CALCULATE FACTORIAL FOR 100 NUMBERS 
    ch := make(chan int) // CREATE CHANNEL TO INPUT NUMBERS 

    go func() { 
     for i := 1; i <= 100; i++ { 
      ch <- i 
     } 
     close(ch) // CLOSE CHANNEL WHEN ALL NUMBERS HAVE BEEN WRITTEM 
    }() 

    return ch 
} 

func _inListener(ch chan int) chan int { 
    rec := make(chan int) // CHANNEL RECEIVED FROM GENERATOR 
    go func() { 
     for num := range ch { // RECEIVE THE INPUT NUMBERS FROM GENERATOR 
      result := factorial(num) // RESULT IS A NEW CHANNEL CREATED 
      rec <- <-result // MERGE INTO A SINGLE CHANNEL; rec 
      close(result) 
     } 
     close(rec) 
    }() 
    return rec // RETURN THE DEDICATED CHANNEL TO RECEIVE ALL OUTPUTS 
} 

func factorial(n int) chan int { 
    ch := make(chan int) // MAKE A NEW CHANNEL TO OUTPUT THE RESULT 
    // OF FACTORIAL 
    total := 1 
    for i := n; i > 0; i-- { 
     total *= i 
    } 
    ch <- total 
    return ch // RETURN THE CHANNEL HAVING THE FACTORIAL CALCULATED 
} 

J'ai mis des commentaires, de sorte qu'il devient plus facile de suivre le code.

Répondre

0

Je ne suis pas un expert dans les canaux. J'ai pris ça pour essayer de me familiariser avec go. Un autre problème est l'int n'est pas assez grand pour prendre toutes les factorielles plus de 20 ou plus. Comme vous pouvez le voir, j'ai ajouté un différé de fermeture ainsi qu'un canal logique appelé fait dans la fonction du générateur. Le reste des changements ne sont probablement pas nécessaires. Avec les canaux, vous devez vous assurer que quelque chose est prêt à enlever une valeur sur le canal lorsque vous mettez quelque chose sur un canal. Sinon impasse. Aussi, en utilisant

aller courir -Course main.go

aide au moins voir quelle ligne (s) sont à l'origine des problèmes.

J'espère que cela aide et n'est pas supprimé pour être hors sujet.

j'ai pu retirer l'impasse en faisant ceci:

package main 

import (
    "fmt" 
) 

func main() { 
    _gen := generator() 
    _inChannel := _inListener(_gen) 
    for val := range _inChannel { 
     fmt.Print(val, " -- \n") 
    } 
} 

func generator() chan int { // NEED TO CALCULATE FACTORIAL FOR 100 NUMBERS 
    ch := make(chan int) // CREATE CHANNEL TO INPUT NUMBERS 
    done := make(chan bool) 
    go func() { 
     defer close(ch) 
     for i := 1; i <= 100; i++ { 
      ch <- i 
     } 
     //close(ch) // CLOSE CHANNEL WHEN ALL NUMBERS HAVE BEEN WRITTEM 
     done <- true 
    }() 

    // this function will pull off the done for each function call above. 
    go func() { 
     for i := 1; i < 100; i++ { 
      <-done 
     } 
    }() 

    return ch 
} 

func _inListener(ch chan int) chan int { 
    rec := make(chan int) // CHANNEL RECEIVED FROM GENERATOR 
    go func() { 
     for num := range ch { // RECEIVE THE INPUT NUMBERS FROM GENERATOR 
      result := factorial(num) // RESULT IS A NEW CHANNEL CREATED 
      rec <- result   // MERGE INTO A SINGLE CHANNEL; rec 
     } 
     close(rec) 
    }() 

    return rec // RETURN THE DEDICATED CHANNEL TO RECEIVE ALL OUTPUTS 
} 

func factorial(n int) int { 
    // OF FACTORIAL 
    total := 1 
    for i := n; i > 0; i-- { 
     total *= i 
    } 
    return total // RETURN THE CHANNEL HAVING THE FACTORIAL CALCULATED 
}