0

How to rigger a channel inside the loop where the same channel is consumed. Below is a sample code that does not work. How is this achievable?

https://go.dev/play/p/o5ZhNfw4IFu

package main

import (
    "context"
    "fmt"
    "time"
)

func main() {
    ch1 := make(chan struct{})
    ch2 := make(chan struct{})
    defer close(ch1)
    defer close(ch2)

    ctx, cancel := context.WithTimeout(context.Background(), time.Second*3)
    defer cancel()

    go func() {
        time.Sleep(time.Second * 1)
        ch1 <- struct{}{}
    }()

loop:
    for {
        select {
        case <-ctx.Done():
            fmt.Println("timeout")
            break loop
        case <-ch1:
            fmt.Println("ch1")
            ch2 <- struct{}{} // This here does not work!
        case <-ch2:
            fmt.Println("ch2")
        }
    }

}

Sami Al-Subhi
  • 4,406
  • 9
  • 39
  • 66

1 Answers1

1

1. send data to ch2 inside goroutine

package main

import (
    "context"
    "fmt"
    "time"
)

func main() {
    ch1 := make(chan struct{})
    ch2 := make(chan struct{})
    defer close(ch1)
    defer close(ch2)

    ctx, cancel := context.WithTimeout(context.Background(), time.Second*3)
    defer cancel()

    go func() {
        time.Sleep(time.Second * 1)
        ch1 <- struct{}{}
    }()

loop:
    for {
        select {
        case <-ctx.Done():
            fmt.Println("timeout")
            break loop
        case <-ch1:
            fmt.Println("ch1")
            go func() {
                ch2 <- struct{}{}
            }()
        case <-ch2:
            fmt.Println("ch2")
        }
    }

}

or

2. make ch2 buffered

package main

import (
    "context"
    "fmt"
    "time"
)

func main() {
    ch1 := make(chan struct{})
    ch2 := make(chan struct{}, 1)
    defer close(ch1)
    defer close(ch2)

    ctx, cancel := context.WithTimeout(context.Background(), time.Second*3)
    defer cancel()

    go func() {
        time.Sleep(time.Second * 1)
        ch1 <- struct{}{}
    }()

loop:
    for {
        select {
        case <-ctx.Done():
            fmt.Println("timeout")
            break loop
        case <-ch1:
            fmt.Println("ch1")
            ch2 <- struct{}{}
        case <-ch2:
            fmt.Println("ch2")
        }
    }

}
Rahmat Fathoni
  • 1,272
  • 1
  • 2
  • 8
  • I have a similar [question](https://stackoverflow.com/questions/71916607/load-data-from-reading-files-during-startup-and-then-process-new-files-and-clear/) where I am using channels too. I wanted to see if you can help me out there. – dragons Apr 19 '22 at 05:25