golang channel behaviour with for loops

I'm curious about the behaviour of channels and how they work in relation to loops. Suppose I have the following code:

Consumer

tick := time.Tick(time.Duration(2) * time.Second)
for {
    select {
    case <-tick:
        p.channel <-true
    }
}

And I have a goroutine that has the following:

Processor

for {
    select {
    case canProcess := <-p.channel:
        // synchronous process that takes longer than 2 seconds
    case <-p.stop:
        return
    }
}

What happens when the Consumer pushes to the channel faster than the Processor can complete its synchronous process?

Do they pile up waiting for the Processor to complete or do they skip a "beat" as such?

If they pile up, is there potential for memory leaking?

I know I can put the synchronous process in a goroutine instead, but this is really to understand how channels behave. (i.e. my example has a 2-second tick, but it doesn't have to).

1 answer

  • answered 2018-02-13 01:17 Adrian Witas

    select will only invoke next time.Tick if previous case corresponding code was completed,
    you can still have some lever by specifying size of channel i.e channel := make(chan bool,10)

    See below:

    func main() {
    
        channel := make(chan bool, 10)
        go func() {
            tick := time.Tick(time.Duration(1) * time.Second)
            for {
                select {
                case <-tick:
                    fmt.Printf("Producer: TICK %v\n", time.Now())
                    channel <- true
                    }
            }
        }()
    
        for {
            select {
            case canProcess := <-channel:
                time.Sleep(3*  time.Second)
                fmt.Printf("Consumer: Completed : %v\n")
                fmt.Printf("%v\n", canProcess)
            }
        }
    }