Search code examples
go

Why is not possible a ubf channel dispatch/write into a other ubf channel of same struct/consumer?


Until now I was considering go channels "as the same as an event queue" where I usually execute an action/consumer and then dispatch the next action. I tried to implement this same behavior with go channels and it seems not to work or is not well written. Could you please explain why chan-group2 is never consumed after being "feed" by chan1 execution? here is the code example:

package main

import (
    "fmt"
)

type Runner struct {
    group1 chan []byte
    group2 chan []byte
}

func (r *Runner) Run() {
    for {
        select {
        case info := <-r.group1:
            fmt.Printf("%s\n", info)
            r.group2 <- []byte("hello from group 2") // try to dispatch to other channel
        case info2 := <-r.group2: // but it is never triggered
            fmt.Printf("%s\n", info2)
        }
    }
}

func newRunner() *Runner {
    return &Runner{
        group1: make(chan []byte),
        group2: make(chan []byte),
    }
}

func main() {
    runner := newRunner()
    go runner.Run()
    runner.group1 <- []byte("hello from group 1")

}


Solution

  • Your code will block on send to group2:

    r.group2 <- []byte("hello from group 2") 
    

    because the chan is not buffered and there is no consumer ready to receive from the chan.

    So one option is to make the chan group2 buffered, ie group2: make(chan []byte, 1), this allows the send operation to succeed and in the next iteration of the loop receive from group2 chan would happen.

    Another option would be to have separate goroutine consuming from group2 chan, ie as a quick test in your code you could just launch the Run twice:

        runner := newRunner()
        go runner.Run()
        go runner.Run()
        runner.group1 <- []byte("hello from group 1")
    

    Note that the code is currently flawed as the main func should wait for the goroutines to exit (ie via cancelling an context) before exiting, currently as soon as the send in the main happens (runner.group1 <- []byte("hello from group 1")) the main exits and you may or may not see the output from the Run...