Search code examples
goconcurrencychannelgoroutine

Go, passing data to channel


I have an issue. Here is example: https://play.golang.org/p/QSWY2INQuSE

func Avg(c chan string, wg *sync.WaitGroup) {
    defer wg.Done()
    c <- "test"
}

func main() {
    var wg sync.WaitGroup
    c := make(chan string)

    timer1 := time.NewTicker(5 * time.Second)

    for {
        select {
        case <-timer1.C:
            wg.Add(1)
            go Avg(c, &wg)
            wg.Wait()
        }
    }
    fmt.Println(<-c)
}

Why data does not reach fmt.Println(<-c)

Thank you!


Solution

  • Because you have an endless for, so the last fmt.Println() statement is never reached.

    You have to break out of the loop if you want the last fmt.Println() statement to ever execute, for example:

    loop:
        for {
            select {
            case <-timer1.C:
                wg.Add(1)
                go Avg(c, &wg)
                wg.Wait()
                break loop
            }
        }
        fmt.Println(<-c)
    

    Note that you have to use a label, else the break would only break out of the select statement (and not from the for loop).

    Also note that this alone won't work, as the channel is unbuffered, and thus Avg() will be blocked forever, trying to send a value on c while noone is ever trying to receive from it.

    This simple example can be made working if you create the channel to be buffered:

    c := make(chan string, 1) // Buffer for 1 value
    

    Now it works and prints (try it on the Go Playground):

    test