当我尝试模拟风扇输入时出现死锁-通过阶乘计算扇出

I am trying the fan in - fan out pattern with a factorial problem. But I am getting:

fatal error: all goroutines are asleep - deadlock!

and unable to identify the reason for deadlock.

I am trying to concurrently calculate factorial for 100 numbers using the fan-in fan-out pattern.

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
}

I have put in comments, so that it becomes easier to follow the code.

I'm no expert in channels. I've taking on this to try and get more familiar with go. Another issue is the int isn't large enough to take all factorials over 20 or so. As you can see, I added a defer close as well as a logical channel called done in the generator func. The rest of the changes probably aren't needed. With channels you need to make sure something is ready to take off a value on the channel when you put something on a channel. Otherwise deadlock. Also, using

go run -race main.go

helps at least see which line(s) are causing problems.

I hope this helps and isn't removed for being off topic.

I was able to remove the deadlock by doing this:

package main

import (
    "fmt"
)

func main() {
    _gen := generator()
    _inChannel := _inListener(_gen)
    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
    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
}