Search code examples
goconcurrencywaitchannelgoroutine

Issue in Passing data from one goroutine to another using channels


I have been able to develop below code which should pass data from one routine to another using go channels:

package main

import (
    "fmt"
    "sync"
)

func generateNumbers(total int, wg *sync.WaitGroup) {
    defer wg.Done()
    ch :=make(chan int)

    sum :=0
    for idx := 1; idx <= total; idx++ {
        fmt.Printf("Generating number %d\n", idx)
        sum =sum+idx
        ch <- sum
    }
}

func printNumbers(wg *sync.WaitGroup, ch chan  int) {
    defer wg.Done()

    fmt.Printf("Sum is now",ch)
    for idx := 1; idx <= 3; idx++ {
        fmt.Printf("Printing number %d\n", idx)
    }
}

func main() {
    var wg sync.WaitGroup

    ch1 :=make(chan int)

    wg.Add(2)
    go printNumbers(&wg,ch1)
    go generateNumbers(3, &wg)

    fmt.Println("Waiting for goroutines to finish...")
    wg.Wait()
    fmt.Println("Done!")
}

I am trying to pass data ( Value of Sum ) from generateNumbers to printNumbers routine.

But i am getting below issue:

Waiting for goroutines to finish...
Generating number 1
Sum is now%!(EXTRA chan int=0xc000102060)Printing number 1
Printing number 2
Printing number 3
fatal error: all goroutines are asleep - deadlock!
goroutine 1 [semacquire]:
sync.runtime_Semacquire(0xc000118270?)
    /usr/local/go/src/runtime/sema.go:62 +0x27
sync.(*WaitGroup).Wait(0x4ba3a8?)
    /usr/local/go/src/sync/waitgroup.go:116 +0x4b
main.main()
    /tmp/tgPhZuPV77.go:42 +0x12f

goroutine 19 [chan send]:
main.generateNumbers(0x3, 0x0?)
    /tmp/tgPhZuPV77.go:19 +0xf2
created by main.main
    /tmp/tgPhZuPV77.go:39 +0xe5
exit status 2

Please help, I am new to Golang.


Solution

  • There are some errors in the above program.

    1. These two functions printNumbers and generateNumbers must be using the same chan variable.
    2. You should read data from ch for chan variable.
    3. That funcion generateNumbers shouldn't declare and create chan variable repeatedly.

    I have modified the above code as follows:

    func generateNumbers(total int, wg *sync.WaitGroup, ch chan int) {
        defer wg.Done()
    
        sum := 0
        for idx := 1; idx <= total; idx++ {
            fmt.Printf("Generating number %d\n", idx)
            sum = sum + idx
            ch <- sum
        }
    }
    
    func printNumbers(wg *sync.WaitGroup, ch chan int) {
        defer wg.Done()
    
        fmt.Printf("Sum is now:\n")
        for idx := 1; idx <= 3; idx++ {
            sum := <-ch
            fmt.Printf("Printing number %d %d\n", idx, sum)
        }
    }
    
    func main() {
        var wg sync.WaitGroup
    
        ch1 := make(chan int)
    
        wg.Add(2)
        go printNumbers(&wg, ch1)
        go generateNumbers(3, &wg, ch1)
    
        fmt.Println("Waiting for goroutines to finish...")
        wg.Wait()
        fmt.Println("Done!")
    }