Channels in control flow
We are almost done with the discussion about the channel. The last thing that I wanted to discuss is how to handle control flow in channels. we are going to discuss the following.
IF statement
For Loop
Select statements.
func main() {
wg := &sync.WaitGroup{}
ch := make(chan int,1)
wg.Add(2)
go func (ch chan int, wg *sync.WaitGroup) {
if msg, ok := <- ch; ok {
fmt.Println(msg, ok) // receiveing the message from channel
}
wg.Done()
}(ch,wg)
go func (ch chan int, wg *sync.WaitGroup) {
// close(ch);
ch <- 42 // sending the message from channel
wg.Done()
}(ch,wg)
wg.Wait()
}
For loop
func main() {
wg := &sync.WaitGroup{}
ch := make(chan int,1)
wg.Add(2)
go func (ch chan int, wg *sync.WaitGroup) {
// we are using this for loop show that we can address the issue where we don't know the exact number of message going to come in.
for msg := range ch {
fmt.Println(msg)
}
//for i := 0; i < 10; i++ {
//fmt.Println(<-ch)
//}
wg.Done()
}(ch,wg)
go func (ch chan int, wg *sync.WaitGroup) {
for i := 0; i < 10; i++ {
ch <- i
}
close(ch)
wg.Done()
}(ch,wg)
wg.Wait()
}
Select Statements
Select Statements are similar to switch statements in their syntax. But in the select statement, we check either send or receive from a channel.
ch1 := make(chan int)
ch2 := make(chan string)
select {
case i := <-ch1:
...
case ch2 <- "hello":
...
}
Here in the above code in the first case, we are checking if we receive the message from ch1
into the variable i
and in another case we are sending a string hello
to the ch2
.
Now if one of the channels is available to act so if we have a message waiting on ch1
or if we waiting to send a message on ch2
then that case will be taken. If both of the cases are available then Randamoly decided which case going to fire there is no pre-determined order, unlike switch
statement where the first case that matches gets acted upon. In select
statement, there is no pre-determined order if multiple cases can be acted upon at the same time.
Another thing about select
statement if you see the above code. Here select
statement will block until it acts in one of those cases. So if there is no message on ch1
and ch2
is not ready for the message we are going to stop the execution of the current goroutine until we receive the message from ch1
or send a message from ch2
. So entire goroutine is going to stop here until we get one of those conditions. This is what we call a blocking select
statement. And make it non-blocking select we can add a default
case .
ch1 := make(chan int)
ch2 := make(chan string)
select {
case i := <-ch1:
...
case ch2 <- "hello":
...
default:
// use default case for non-blocking select
}